Core/DataStores: Updated db2 structures to 9.0.2
Port From (https://github.com/TrinityCore/TrinityCore/commit/b82a3a557a7bf13d48342ea189325550059b622d)
This commit is contained in:
@@ -84,6 +84,12 @@ namespace Game.Achievements
|
||||
return false;
|
||||
}
|
||||
|
||||
if (achievement.CovenantID != 0 && referencePlayer.m_playerData.CovenantID != achievement.CovenantID)
|
||||
{
|
||||
Log.outTrace(LogFilter.Achievement, $"CanUpdateCriteriaTree: (Id: {criteria.Id} Type {criteria.Entry.Type} Achievement {achievement.Id}) Wrong covenant");
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CanUpdateCriteriaTree(criteria, tree, referencePlayer);
|
||||
}
|
||||
|
||||
@@ -535,7 +541,7 @@ namespace Game.Achievements
|
||||
//! Since no common attributes were found, (not even in titleRewardFlags field)
|
||||
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
|
||||
//! condition fields to the condition system.
|
||||
uint titleId = reward.TitleId[achievement.Id == 1793 ? _owner.m_playerData.NativeSex : (_owner.GetTeam() == Team.Alliance ? 0 : 1)];
|
||||
uint titleId = reward.TitleId[achievement.Id == 1793 ? (int)_owner.GetNativeSex() : (_owner.GetTeam() == Team.Alliance ? 0 : 1)];
|
||||
if (titleId != 0)
|
||||
{
|
||||
CharTitlesRecord titleEntry = CliDB.CharTitlesStorage.LookupByKey(titleId);
|
||||
|
||||
@@ -138,6 +138,10 @@ namespace Game.Achievements
|
||||
case CriteriaTypes.OwnBattlePetCount:
|
||||
case CriteriaTypes.HonorLevelReached:
|
||||
case CriteriaTypes.PrestigeReached:
|
||||
case CriteriaTypes.CompleteQuestAccumulate:
|
||||
case CriteriaTypes.BoughtItemFromVendor:
|
||||
case CriteriaTypes.SoldItemToVendor:
|
||||
case CriteriaTypes.TravelledToArea:
|
||||
SetCriteriaProgress(criteria, 1, referencePlayer, ProgressType.Accumulate);
|
||||
break;
|
||||
// std case: increment at miscValue1
|
||||
@@ -437,6 +441,9 @@ namespace Game.Achievements
|
||||
case CriteriaTypes.EarnHonorXp:
|
||||
case CriteriaTypes.RelicTalentUnlocked:
|
||||
case CriteriaTypes.ReachAccountHonorLevel:
|
||||
case CriteriaTypes.MythicKeystoneCompleted:
|
||||
case CriteriaTypes.ApplyConduit:
|
||||
case CriteriaTypes.ConvertItemsToCurrency:
|
||||
break; // Not implemented yet :(
|
||||
}
|
||||
|
||||
@@ -812,6 +819,10 @@ namespace Game.Achievements
|
||||
case CriteriaTypes.ReachAccountHonorLevel:
|
||||
case CriteriaTypes.HeartOfAzerothArtifactPowerEarned:
|
||||
case CriteriaTypes.HeartOfAzerothLevelReached:
|
||||
case CriteriaTypes.CompleteQuestAccumulate:
|
||||
case CriteriaTypes.BoughtItemFromVendor:
|
||||
case CriteriaTypes.SoldItemToVendor:
|
||||
case CriteriaTypes.TravelledToArea:
|
||||
return progress.Counter >= requiredAmount;
|
||||
case CriteriaTypes.CompleteAchievement:
|
||||
case CriteriaTypes.CompleteQuest:
|
||||
@@ -942,6 +953,9 @@ namespace Game.Achievements
|
||||
case CriteriaTypes.WinDuel:
|
||||
case CriteriaTypes.WinRatedArena:
|
||||
case CriteriaTypes.WonAuctions:
|
||||
case CriteriaTypes.CompleteQuestAccumulate:
|
||||
case CriteriaTypes.BoughtItemFromVendor:
|
||||
case CriteriaTypes.SoldItemToVendor:
|
||||
if (miscValue1 == 0)
|
||||
return false;
|
||||
break;
|
||||
@@ -1188,6 +1202,10 @@ namespace Game.Achievements
|
||||
if (miscValue1 != criteria.Entry.Asset)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaTypes.TravelledToArea:
|
||||
if (miscValue1 != criteria.Entry.Asset)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1227,8 +1245,8 @@ namespace Game.Achievements
|
||||
bool ModifierSatisfied(ModifierTreeRecord modifier, ulong miscValue1, ulong miscValue2, Unit unit, Player referencePlayer)
|
||||
{
|
||||
uint reqValue = modifier.Asset;
|
||||
int secondaryAsset = modifier.SecondaryAsset;
|
||||
int tertiaryAsset = modifier.TertiaryAsset;
|
||||
int secondaryAsset = modifier.SecondaryAsset;
|
||||
int tertiaryAsset = modifier.TertiaryAsset;
|
||||
|
||||
switch ((CriteriaAdditionalCondition)modifier.Type)
|
||||
{
|
||||
@@ -1621,7 +1639,7 @@ namespace Game.Achievements
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.SourceNativeSex: // 98
|
||||
if (referencePlayer.m_playerData.NativeSex != reqValue)
|
||||
if (referencePlayer.GetNativeSex() != (Gender)reqValue)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.Skill: // 99
|
||||
@@ -1656,7 +1674,7 @@ namespace Game.Achievements
|
||||
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(reqValue);
|
||||
if (questBit != 0)
|
||||
if ((referencePlayer.m_activePlayerData.QuestCompleted[((int)questBit - 1) >> 6] & (1ul << (((int)questBit - 1) & 63))) == 0)
|
||||
return false;
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.CompletedQuest: // 111
|
||||
if (referencePlayer.GetQuestStatus(reqValue) != QuestStatus.Complete)
|
||||
@@ -2402,7 +2420,7 @@ namespace Game.Achievements
|
||||
break;
|
||||
}
|
||||
case CriteriaAdditionalCondition.SourceLevel120: // 264
|
||||
if (referencePlayer.GetLevel() != 120)
|
||||
if (referencePlayer.GetLevel() != 60)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.SelectedAzeriteEssenceRankLower: // 266
|
||||
@@ -2441,8 +2459,54 @@ namespace Game.Achievements
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CriteriaAdditionalCondition.SourceLevelInRangeCt: // 268
|
||||
{
|
||||
uint level = referencePlayer.GetLevel();
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(reqValue, 0);
|
||||
if (levels.HasValue)
|
||||
{
|
||||
if (secondaryAsset != 0)
|
||||
return level >= levels.Value.MinLevelWithDelta && level <= levels.Value.MaxLevelWithDelta;
|
||||
return level >= levels.Value.MinLevel && level <= levels.Value.MaxLevel;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CriteriaAdditionalCondition.TargetLevelInRangeCt: // 269
|
||||
{
|
||||
if (!unit)
|
||||
return false;
|
||||
|
||||
uint level = unit.GetLevel();
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(reqValue, 0);
|
||||
if (levels.HasValue)
|
||||
{
|
||||
if (secondaryAsset != 0)
|
||||
return level >= levels.Value.MinLevelWithDelta && level <= levels.Value.MaxLevelWithDelta;
|
||||
return level >= levels.Value.MinLevel && level <= levels.Value.MaxLevel;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CriteriaAdditionalCondition.SourceLevelGreaterCt: // 272
|
||||
{
|
||||
uint level = referencePlayer.GetLevel();
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(reqValue, 0);
|
||||
if (levels.HasValue)
|
||||
return secondaryAsset != 0 ? level >= levels.Value.MinLevelWithDelta : level >= levels.Value.MinLevel;
|
||||
return false;
|
||||
}
|
||||
case CriteriaAdditionalCondition.TargetLevelGreaterCt: // 273
|
||||
{
|
||||
if (!unit)
|
||||
return false;
|
||||
|
||||
uint level = unit.GetLevel();
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(reqValue, 0);
|
||||
if (levels.HasValue)
|
||||
return secondaryAsset != 0 ? level >= levels.Value.MinLevelWithDelta : level >= levels.Value.MinLevel;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
case CriteriaAdditionalCondition.MapOrCosmeticMap: // 280
|
||||
{
|
||||
MapRecord map = referencePlayer.GetMap().GetEntry();
|
||||
@@ -2450,6 +2514,60 @@ namespace Game.Achievements
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case CriteriaAdditionalCondition.Covenant: // 288
|
||||
if (referencePlayer.m_playerData.CovenantID != reqValue)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.Soulbind: // 291
|
||||
if (referencePlayer.m_playerData.SoulbindID != reqValue)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.SourceAreaOrZoneInGroup: // 293
|
||||
{
|
||||
var areas = Global.DB2Mgr.GetAreasForGroup(reqValue);
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(referencePlayer.GetAreaId());
|
||||
if (area != null)
|
||||
foreach (uint areaInGroup in areas)
|
||||
if (areaInGroup == area.Id || areaInGroup == area.ParentAreaID)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
case CriteriaAdditionalCondition.SourceInSpecificChromieTime: // 300
|
||||
if (referencePlayer.m_activePlayerData.UiChromieTimeExpansionID != reqValue)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.SourceInAnyChromieTime: // 301
|
||||
if (referencePlayer.m_activePlayerData.UiChromieTimeExpansionID == 0)
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.SourceRuneforgeLegendaryKnown: // 303
|
||||
{
|
||||
int block = (int)reqValue / 32;
|
||||
if (block >= referencePlayer.m_activePlayerData.RuneforgePowers.Size())
|
||||
return false;
|
||||
|
||||
uint bit = reqValue % 32;
|
||||
return (referencePlayer.m_activePlayerData.RuneforgePowers[block] & (1u << (int)bit)) != 0;
|
||||
}
|
||||
case CriteriaAdditionalCondition.ShapeshiftFormCustomizationDisplay: // 308
|
||||
{
|
||||
ShapeshiftFormModelData formModelData = Global.DB2Mgr.GetShapeshiftFormModelData(referencePlayer.GetRace(), referencePlayer.GetNativeSex(), (ShapeShiftForm)secondaryAsset);
|
||||
if (formModelData == null)
|
||||
return false;
|
||||
|
||||
uint formChoice = referencePlayer.GetCustomizationChoice(formModelData.OptionID);
|
||||
var choiceIndex = formModelData.Choices.FindIndex(choice => { return choice.Id == formChoice; });
|
||||
if (choiceIndex == -1)
|
||||
return false;
|
||||
|
||||
if (reqValue != formModelData.Displays[choiceIndex].DisplayID)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case CriteriaAdditionalCondition.SourceFlying: // 311
|
||||
if (!referencePlayer.IsFlying())
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2851,7 +2969,7 @@ namespace Game.Achievements
|
||||
{
|
||||
return _criteriasByFailEvent[(int)condition].LookupByKey(asset);
|
||||
}
|
||||
|
||||
|
||||
public CriteriaDataSet GetCriteriaDataSet(Criteria criteria)
|
||||
{
|
||||
return _criteriaDataMap.LookupByKey(criteria.Id);
|
||||
@@ -2917,7 +3035,7 @@ namespace Game.Achievements
|
||||
}
|
||||
|
||||
public class CriteriaTree
|
||||
{
|
||||
{
|
||||
public uint Id;
|
||||
public CriteriaTreeRecord Entry;
|
||||
public AchievementRecord Achievement;
|
||||
|
||||
@@ -1552,7 +1552,7 @@ namespace Game.BattleGrounds
|
||||
// creature.SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL);
|
||||
// casting visual effect
|
||||
creature.SetChannelSpellId(BattlegroundConst.SpellSpiritHealChannel);
|
||||
creature.SetChannelSpellXSpellVisualId(BattlegroundConst.SpellSpiritHealChannelVisual);
|
||||
creature.SetChannelVisual(new SpellCastVisual(BattlegroundConst.SpellSpiritHealChannelVisual, 0));
|
||||
//creature.CastSpell(creature, SPELL_SPIRIT_HEAL_CHANNEL, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,14 @@ namespace Game.Cache
|
||||
_characterCacheByNameStore[name] = characterCacheEntry;
|
||||
}
|
||||
|
||||
public void UpdateCharacterGender(ObjectGuid guid, byte gender)
|
||||
{
|
||||
if (!_characterCacheStore.ContainsKey(guid))
|
||||
return;
|
||||
|
||||
_characterCacheStore[guid].Sex = (Gender)gender;
|
||||
}
|
||||
|
||||
public void UpdateCharacterLevel(ObjectGuid guid, byte level)
|
||||
{
|
||||
if (!_characterCacheStore.ContainsKey(guid))
|
||||
|
||||
@@ -23,6 +23,7 @@ using Game.Entities;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Game.Chat
|
||||
{
|
||||
@@ -542,11 +543,23 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
if (handler.GetSession() != null)
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id,
|
||||
{
|
||||
int maxLevel = 0;
|
||||
var questLevels = Global.DB2Mgr.GetContentTuningData(qInfo.ContentTuningId, handler.GetSession().GetPlayer().m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (questLevels.HasValue)
|
||||
maxLevel = questLevels.Value.MaxLevel;
|
||||
|
||||
int scalingFactionGroup = 0;
|
||||
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(qInfo.ContentTuningId);
|
||||
if (contentTuning != null)
|
||||
scalingFactionGroup = contentTuning.GetScalingFactionGroup();
|
||||
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id,
|
||||
handler.GetSession().GetPlayer().GetQuestLevel(qInfo),
|
||||
handler.GetSession().GetPlayer().GetQuestMinLevel(qInfo),
|
||||
qInfo.MaxScalingLevel, qInfo.ScalingFactionGroup,
|
||||
maxLevel, scalingFactionGroup,
|
||||
title, statusStr);
|
||||
}
|
||||
else
|
||||
handler.SendSysMessage(CypherStrings.QuestListConsole, qInfo.Id, title, statusStr);
|
||||
|
||||
@@ -594,11 +607,23 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
if (handler.GetSession() != null)
|
||||
{
|
||||
int maxLevel = 0;
|
||||
var questLevels = Global.DB2Mgr.GetContentTuningData(qInfo.ContentTuningId, handler.GetSession().GetPlayer().m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (questLevels.HasValue)
|
||||
maxLevel = questLevels.Value.MaxLevel;
|
||||
|
||||
int scalingFactionGroup = 0;
|
||||
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(qInfo.ContentTuningId);
|
||||
if (contentTuning != null)
|
||||
scalingFactionGroup = contentTuning.GetScalingFactionGroup();
|
||||
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id,
|
||||
handler.GetSession().GetPlayer().GetQuestLevel(qInfo),
|
||||
handler.GetSession().GetPlayer().GetQuestMinLevel(qInfo),
|
||||
qInfo.MaxScalingLevel, qInfo.ScalingFactionGroup,
|
||||
maxLevel, scalingFactionGroup,
|
||||
_title, statusStr);
|
||||
}
|
||||
else
|
||||
handler.SendSysMessage(CypherStrings.QuestListConsole, qInfo.Id, _title, statusStr);
|
||||
|
||||
|
||||
@@ -591,7 +591,7 @@ namespace Game.Chat
|
||||
if (spellInfo == null)
|
||||
return false;
|
||||
|
||||
SpellNonMeleeDamage damageInfo = new SpellNonMeleeDamage(attacker, target, spellInfo, spellInfo.GetSpellXSpellVisualId(attacker), spellInfo.SchoolMask);
|
||||
SpellNonMeleeDamage damageInfo = new SpellNonMeleeDamage(attacker, target, spellInfo, new Networking.Packets.SpellCastVisual(spellInfo.GetSpellXSpellVisualId(attacker), 0), spellInfo.SchoolMask);
|
||||
damageInfo.damage = damage_;
|
||||
attacker.DealDamageMods(damageInfo.target, ref damageInfo.damage, ref damageInfo.absorb);
|
||||
target.DealSpellDamage(damageInfo, true);
|
||||
@@ -1596,7 +1596,7 @@ namespace Game.Chat
|
||||
mapId = target.GetMapId();
|
||||
areaId = target.GetAreaId();
|
||||
alive = target.IsAlive() ? handler.GetCypherString(CypherStrings.Yes) : handler.GetCypherString(CypherStrings.No);
|
||||
gender = (Gender)(byte)target.m_playerData.NativeSex;
|
||||
gender = target.GetNativeSex();
|
||||
}
|
||||
// get additional information from DB
|
||||
else
|
||||
@@ -2367,7 +2367,7 @@ namespace Game.Chat
|
||||
if (caster)
|
||||
{
|
||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, player.GetMapId(), SPELL_UNSTUCK_ID, player.GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||
Spell.SendCastResult(caster, spellInfo, SPELL_UNSTUCK_VISUAL, castId, SpellCastResult.CantDoThatRightNow);
|
||||
Spell.SendCastResult(caster, spellInfo, new Networking.Packets.SpellCastVisual(SPELL_UNSTUCK_VISUAL, 0), castId, SpellCastResult.CantDoThatRightNow);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1727,11 +1727,30 @@ namespace Game
|
||||
|
||||
public static bool IsPlayerMeetingCondition(Player player, PlayerConditionRecord condition)
|
||||
{
|
||||
if (condition.MinLevel != 0 && player.GetLevel() < condition.MinLevel)
|
||||
return false;
|
||||
ContentTuningLevels? levels = Global.DB2Mgr.GetContentTuningData(condition.ContentTuningID, player.m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (levels.HasValue)
|
||||
{
|
||||
byte minLevel = (byte)(condition.Flags.HasAnyFlag(0x800) ? levels.Value.MinLevelWithDelta : levels.Value.MinLevel);
|
||||
byte maxLevel = 0;
|
||||
if (!condition.Flags.HasAnyFlag(0x20))
|
||||
maxLevel = (byte)(condition.Flags.HasAnyFlag(0x800) ? levels.Value.MaxLevelWithDelta : levels.Value.MaxLevel);
|
||||
if (condition.Flags.HasAnyFlag(0x80))
|
||||
{
|
||||
if (minLevel != 0 && player.GetLevel() >= minLevel && (maxLevel == 0 || player.GetLevel() <= maxLevel))
|
||||
return false;
|
||||
|
||||
if (condition.MaxLevel != 0 && player.GetLevel() > condition.MaxLevel)
|
||||
return false;
|
||||
if (maxLevel != 0 && player.GetLevel() <= maxLevel && (minLevel == 0 || player.GetLevel() >= minLevel))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (minLevel != 0 && player.GetLevel() < minLevel)
|
||||
return false;
|
||||
|
||||
if (maxLevel != 0 && player.GetLevel() > maxLevel)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (condition.RaceMask != 0 && !Convert.ToBoolean(player.GetRaceMask() & condition.RaceMask))
|
||||
return false;
|
||||
@@ -1742,7 +1761,7 @@ namespace Game
|
||||
if (condition.Gender >= 0 && (int)player.GetGender() != condition.Gender)
|
||||
return false;
|
||||
|
||||
if (condition.NativeGender >= 0 && player.m_playerData.NativeSex != condition.NativeGender)
|
||||
if (condition.NativeGender >= 0 && player.GetNativeSex() != (Gender)condition.NativeGender)
|
||||
return false;
|
||||
|
||||
if (condition.PowerType != -1 && condition.PowerTypeComp != 0)
|
||||
@@ -2140,6 +2159,9 @@ namespace Game
|
||||
if (condition.ModifierTreeID != 0 && !player.ModifierTreeSatisfied(condition.ModifierTreeID))
|
||||
return false;
|
||||
|
||||
if (condition.CovenantID != 0 && player.m_playerData.CovenantID != condition.CovenantID)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,14 +91,20 @@ namespace Game.DataStorage
|
||||
BattlemasterListStorage = ReadDB2<BattlemasterListRecord>("BattlemasterList.db2", HotfixStatements.SEL_BATTLEMASTER_LIST, HotfixStatements.SEL_BATTLEMASTER_LIST_LOCALE);
|
||||
BroadcastTextStorage = ReadDB2<BroadcastTextRecord>("BroadcastText.db2", HotfixStatements.SEL_BROADCAST_TEXT, HotfixStatements.SEL_BROADCAST_TEXT_LOCALE);
|
||||
CfgRegionsStorage = ReadDB2<Cfg_RegionsRecord>("Cfg_Regions.db2", HotfixStatements.SEL_CFG_REGIONS);
|
||||
CharacterFacialHairStylesStorage = ReadDB2<CharacterFacialHairStylesRecord>("CharacterFacialHairStyles.db2", HotfixStatements.SEL_CHARACTER_FACIAL_HAIR_STYLES);
|
||||
CharBaseSectionStorage = ReadDB2<CharBaseSectionRecord>("CharBaseSection.db2", HotfixStatements.SEL_CHAR_BASE_SECTION);
|
||||
CharSectionsStorage = ReadDB2<CharSectionsRecord>("CharSections.db2", HotfixStatements.SEL_CHAR_SECTIONS);
|
||||
CharStartOutfitStorage = ReadDB2<CharStartOutfitRecord>("CharStartOutfit.db2", HotfixStatements.SEL_CHAR_START_OUTFIT);
|
||||
CharTitlesStorage = ReadDB2<CharTitlesRecord>("CharTitles.db2", HotfixStatements.SEL_CHAR_TITLES, HotfixStatements.SEL_CHAR_TITLES_LOCALE);
|
||||
CharacterLoadoutStorage = ReadDB2<CharacterLoadoutRecord>("CharacterLoadout.db2", HotfixStatements.SEL_CHARACTER_LOADOUT);
|
||||
CharacterLoadoutItemStorage = ReadDB2<CharacterLoadoutItemRecord>("CharacterLoadoutItem.db2", HotfixStatements.SEL_CHARACTER_LOADOUT_ITEM);
|
||||
ChatChannelsStorage = ReadDB2<ChatChannelsRecord>("ChatChannels.db2", HotfixStatements.SEL_CHAT_CHANNELS, HotfixStatements.SEL_CHAT_CHANNELS_LOCALE);
|
||||
ChrClassesStorage = ReadDB2<ChrClassesRecord>("ChrClasses.db2", HotfixStatements.SEL_CHR_CLASSES, HotfixStatements.SEL_CHR_CLASSES_LOCALE);
|
||||
ChrClassesXPowerTypesStorage = ReadDB2<ChrClassesXPowerTypesRecord>("ChrClassesXPowerTypes.db2", HotfixStatements.SEL_CHR_CLASSES_X_POWER_TYPES);
|
||||
ChrCustomizationChoiceStorage= ReadDB2<ChrCustomizationChoiceRecord>("ChrCustomizationChoice.db2", HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE, HotfixStatements.SEL_CHR_CUSTOMIZATION_CHOICE_LOCALE);
|
||||
ChrCustomizationDisplayInfoStorage= ReadDB2<ChrCustomizationDisplayInfoRecord>("ChrCustomizationDisplayInfo.db2", HotfixStatements.SEL_CHR_CUSTOMIZATION_DISPLAY_INFO);
|
||||
ChrCustomizationElementStorage =ReadDB2<ChrCustomizationElementRecord>("ChrCustomizationElement.db2", HotfixStatements.SEL_CHR_CUSTOMIZATION_ELEMENT);
|
||||
ChrCustomizationOptionStorage =ReadDB2<ChrCustomizationOptionRecord>("ChrCustomizationOption.db2", HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION, HotfixStatements.SEL_CHR_CUSTOMIZATION_OPTION_LOCALE);
|
||||
ChrCustomizationReqStorage =ReadDB2<ChrCustomizationReqRecord>("ChrCustomizationReq.db2", HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ);
|
||||
ChrCustomizationReqChoiceStorage =ReadDB2<ChrCustomizationReqChoiceRecord>("ChrCustomizationReqChoice.db2", HotfixStatements.SEL_CHR_CUSTOMIZATION_REQ_CHOICE);
|
||||
ChrModelStorage =ReadDB2<ChrModelRecord>("ChrModel.db2", HotfixStatements.SEL_CHR_MODEL);
|
||||
ChrRaceXChrModelStorage =ReadDB2<ChrRaceXChrModelRecord>("ChrRaceXChrModel.db2", HotfixStatements.SEL_CHR_RACE_X_CHR_MODEL);
|
||||
ChrRacesStorage = ReadDB2<ChrRacesRecord>("ChrRaces.db2", HotfixStatements.SEL_CHR_RACES, HotfixStatements.SEL_CHR_RACES_LOCALE);
|
||||
ChrSpecializationStorage = ReadDB2<ChrSpecializationRecord>("ChrSpecialization.db2", HotfixStatements.SEL_CHR_SPECIALIZATION, HotfixStatements.SEL_CHR_SPECIALIZATION_LOCALE);
|
||||
CinematicCameraStorage = ReadDB2<CinematicCameraRecord>("CinematicCamera.db2", HotfixStatements.SEL_CINEMATIC_CAMERA);
|
||||
@@ -232,7 +238,6 @@ namespace Game.DataStorage
|
||||
RewardPackStorage = ReadDB2<RewardPackRecord>("RewardPack.db2", HotfixStatements.SEL_REWARD_PACK);
|
||||
RewardPackXCurrencyTypeStorage = ReadDB2<RewardPackXCurrencyTypeRecord>("RewardPackXCurrencyType.db2", HotfixStatements.SEL_REWARD_PACK_X_CURRENCY_TYPE);
|
||||
RewardPackXItemStorage = ReadDB2<RewardPackXItemRecord>("RewardPackXItem.db2", HotfixStatements.SEL_REWARD_PACK_X_ITEM);
|
||||
ScalingStatDistributionStorage = ReadDB2<ScalingStatDistributionRecord>("ScalingStatDistribution.db2", HotfixStatements.SEL_SCALING_STAT_DISTRIBUTION);
|
||||
ScenarioStorage = ReadDB2<ScenarioRecord>("Scenario.db2", HotfixStatements.SEL_SCENARIO, HotfixStatements.SEL_SCENARIO_LOCALE);
|
||||
ScenarioStepStorage = ReadDB2<ScenarioStepRecord>("ScenarioStep.db2", HotfixStatements.SEL_SCENARIO_STEP, HotfixStatements.SEL_SCENARIO_STEP_LOCALE);
|
||||
//SceneScriptStorage = ReadDB2<SceneScriptRecord>("SceneScript.db2", HotfixStatements.SEL_SCENE_SCRIPT);
|
||||
@@ -287,6 +292,7 @@ namespace Game.DataStorage
|
||||
TotemCategoryStorage = ReadDB2<TotemCategoryRecord>("TotemCategory.db2", HotfixStatements.SEL_TOTEM_CATEGORY, HotfixStatements.SEL_TOTEM_CATEGORY_LOCALE);
|
||||
ToyStorage = ReadDB2<ToyRecord>("Toy.db2", HotfixStatements.SEL_TOY, HotfixStatements.SEL_TOY_LOCALE);
|
||||
TransmogHolidayStorage = ReadDB2<TransmogHolidayRecord>("TransmogHoliday.db2", HotfixStatements.SEL_TRANSMOG_HOLIDAY);
|
||||
TransmogIllusionStorage = ReadDB2<TransmogIllusionRecord>("TransmogIllusion.db2", HotfixStatements.SEL_TRANSMOG_ILLUSION);
|
||||
TransmogSetStorage = ReadDB2<TransmogSetRecord>("TransmogSet.db2", HotfixStatements.SEL_TRANSMOG_SET, HotfixStatements.SEL_TRANSMOG_SET_LOCALE);
|
||||
TransmogSetGroupStorage = ReadDB2<TransmogSetGroupRecord>("TransmogSetGroup.db2", HotfixStatements.SEL_TRANSMOG_SET_GROUP, HotfixStatements.SEL_TRANSMOG_SET_GROUP_LOCALE);
|
||||
TransmogSetItemStorage = ReadDB2<TransmogSetItemRecord>("TransmogSetItem.db2", HotfixStatements.SEL_TRANSMOG_SET_ITEM);
|
||||
@@ -440,14 +446,20 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<BattlemasterListRecord> BattlemasterListStorage;
|
||||
public static DB6Storage<BroadcastTextRecord> BroadcastTextStorage;
|
||||
public static DB6Storage<Cfg_RegionsRecord> CfgRegionsStorage;
|
||||
public static DB6Storage<CharacterFacialHairStylesRecord> CharacterFacialHairStylesStorage;
|
||||
public static DB6Storage<CharBaseSectionRecord> CharBaseSectionStorage;
|
||||
public static DB6Storage<CharSectionsRecord> CharSectionsStorage;
|
||||
public static DB6Storage<CharStartOutfitRecord> CharStartOutfitStorage;
|
||||
public static DB6Storage<CharTitlesRecord> CharTitlesStorage;
|
||||
public static DB6Storage<CharacterLoadoutRecord> CharacterLoadoutStorage;
|
||||
public static DB6Storage<CharacterLoadoutItemRecord> CharacterLoadoutItemStorage;
|
||||
public static DB6Storage<ChatChannelsRecord> ChatChannelsStorage;
|
||||
public static DB6Storage<ChrClassesRecord> ChrClassesStorage;
|
||||
public static DB6Storage<ChrClassesXPowerTypesRecord> ChrClassesXPowerTypesStorage;
|
||||
public static DB6Storage<ChrCustomizationChoiceRecord> ChrCustomizationChoiceStorage;
|
||||
public static DB6Storage<ChrCustomizationDisplayInfoRecord> ChrCustomizationDisplayInfoStorage;
|
||||
public static DB6Storage<ChrCustomizationElementRecord> ChrCustomizationElementStorage;
|
||||
public static DB6Storage<ChrCustomizationReqRecord> ChrCustomizationReqStorage;
|
||||
public static DB6Storage<ChrCustomizationReqChoiceRecord> ChrCustomizationReqChoiceStorage;
|
||||
public static DB6Storage<ChrModelRecord> ChrModelStorage;
|
||||
public static DB6Storage<ChrRaceXChrModelRecord> ChrRaceXChrModelStorage;
|
||||
public static DB6Storage<ChrCustomizationOptionRecord> ChrCustomizationOptionStorage;
|
||||
public static DB6Storage<ChrRacesRecord> ChrRacesStorage;
|
||||
public static DB6Storage<ChrSpecializationRecord> ChrSpecializationStorage;
|
||||
public static DB6Storage<CinematicCameraRecord> CinematicCameraStorage;
|
||||
@@ -581,7 +593,6 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<RewardPackRecord> RewardPackStorage;
|
||||
public static DB6Storage<RewardPackXCurrencyTypeRecord> RewardPackXCurrencyTypeStorage;
|
||||
public static DB6Storage<RewardPackXItemRecord> RewardPackXItemStorage;
|
||||
public static DB6Storage<ScalingStatDistributionRecord> ScalingStatDistributionStorage;
|
||||
public static DB6Storage<ScenarioRecord> ScenarioStorage;
|
||||
public static DB6Storage<ScenarioStepRecord> ScenarioStepStorage;
|
||||
//public static DB6Storage<SceneScriptRecord> SceneScriptStorage;
|
||||
@@ -636,6 +647,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<TotemCategoryRecord> TotemCategoryStorage;
|
||||
public static DB6Storage<ToyRecord> ToyStorage;
|
||||
public static DB6Storage<TransmogHolidayRecord> TransmogHolidayStorage;
|
||||
public static DB6Storage<TransmogIllusionRecord> TransmogIllusionStorage;
|
||||
public static DB6Storage<TransmogSetRecord> TransmogSetStorage;
|
||||
public static DB6Storage<TransmogSetGroupRecord> TransmogSetGroupStorage;
|
||||
public static DB6Storage<TransmogSetItemRecord> TransmogSetItemStorage;
|
||||
|
||||
@@ -23,6 +23,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using Framework.Dynamic;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
@@ -123,41 +124,6 @@ namespace Game.DataStorage
|
||||
}
|
||||
}
|
||||
|
||||
foreach (CharacterFacialHairStylesRecord characterFacialStyle in CliDB.CharacterFacialHairStylesStorage.Values)
|
||||
_characterFacialHairStyles.Add(Tuple.Create(characterFacialStyle.RaceID, characterFacialStyle.SexID, (uint)characterFacialStyle.VariationID));
|
||||
|
||||
CliDB.CharacterFacialHairStylesStorage.Clear();
|
||||
|
||||
CharBaseSectionVariation[] sectionToBase = new CharBaseSectionVariation[(int)CharSectionType.Max];
|
||||
foreach (CharBaseSectionRecord charBaseSection in CliDB.CharBaseSectionStorage.Values)
|
||||
{
|
||||
Cypher.Assert(charBaseSection.ResolutionVariationEnum < (byte)CharSectionType.Max, $"SECTION_TYPE_MAX ({(byte)CharSectionType.Max}) must be equal to or greater than {charBaseSection.ResolutionVariationEnum + 1}");
|
||||
Cypher.Assert(charBaseSection.VariationEnum < CharBaseSectionVariation.Max, $"CharBaseSectionVariation.Max {(byte)CharBaseSectionVariation.Max} must be equal to or greater than {charBaseSection.VariationEnum + 1}");
|
||||
|
||||
sectionToBase[charBaseSection.ResolutionVariationEnum] = charBaseSection.VariationEnum;
|
||||
}
|
||||
|
||||
CliDB.CharBaseSectionStorage.Clear();
|
||||
|
||||
MultiMap<Tuple<byte, byte, CharBaseSectionVariation>, Tuple<byte, byte>> addedSections = new MultiMap<Tuple<byte, byte, CharBaseSectionVariation>, Tuple<byte, byte>>();
|
||||
foreach (CharSectionsRecord charSection in CliDB.CharSectionsStorage.Values)
|
||||
{
|
||||
Cypher.Assert(charSection.BaseSection < (byte)CharSectionType.Max, $"SECTION_TYPE_MAX ({(byte)CharSectionType.Max}) must be equal to or greater than {charSection.BaseSection + 1}");
|
||||
|
||||
Tuple<byte, byte, CharBaseSectionVariation> sectionKey = Tuple.Create(charSection.RaceID, charSection.SexID, sectionToBase[charSection.BaseSection]);
|
||||
Tuple<byte, byte> sectionCombination = Tuple.Create(charSection.VariationIndex, charSection.ColorIndex);
|
||||
if (addedSections.Contains(sectionKey, sectionCombination))
|
||||
continue;
|
||||
|
||||
addedSections.Add(sectionKey, sectionCombination);
|
||||
_charSections.Add(sectionKey, charSection);
|
||||
}
|
||||
|
||||
CliDB.CharSectionsStorage.Clear();
|
||||
|
||||
foreach (var outfit in CliDB.CharStartOutfitStorage.Values)
|
||||
_charStartOutfits[(uint)((byte)outfit.RaceID | (outfit.ClassID << 8) | (outfit.SexID << 16))] = outfit;
|
||||
|
||||
var powers = new List<ChrClassesXPowerTypesRecord>();
|
||||
foreach (var chrClasses in CliDB.ChrClassesXPowerTypesStorage.Values)
|
||||
powers.Add(chrClasses);
|
||||
@@ -175,6 +141,71 @@ namespace Game.DataStorage
|
||||
_powersByClass[power.ClassID][power.PowerType] = index;
|
||||
}
|
||||
|
||||
foreach (var customizationChoice in CliDB.ChrCustomizationChoiceStorage.Values)
|
||||
_chrCustomizationChoicesByOption.Add(customizationChoice.ChrCustomizationOptionID, customizationChoice);
|
||||
|
||||
MultiMap<uint, Tuple<uint, byte>> shapeshiftFormByModel = new MultiMap<uint, Tuple<uint, byte>>();
|
||||
Dictionary<uint, ChrCustomizationDisplayInfoRecord> displayInfoByCustomizationChoice = new Dictionary<uint, ChrCustomizationDisplayInfoRecord>();
|
||||
|
||||
// build shapeshift form model lookup
|
||||
foreach (ChrCustomizationElementRecord customizationElement in CliDB.ChrCustomizationElementStorage.Values)
|
||||
{
|
||||
ChrCustomizationDisplayInfoRecord customizationDisplayInfo = CliDB.ChrCustomizationDisplayInfoStorage.LookupByKey(customizationElement.ChrCustomizationDisplayInfoID);
|
||||
if (customizationDisplayInfo != null)
|
||||
{
|
||||
ChrCustomizationChoiceRecord customizationChoice = CliDB.ChrCustomizationChoiceStorage.LookupByKey(customizationElement.ChrCustomizationChoiceID);
|
||||
if (customizationChoice != null)
|
||||
{
|
||||
displayInfoByCustomizationChoice[customizationElement.ChrCustomizationChoiceID] = customizationDisplayInfo;
|
||||
ChrCustomizationOptionRecord customizationOption = CliDB.ChrCustomizationOptionStorage.LookupByKey(customizationChoice.ChrCustomizationOptionID);
|
||||
if (customizationOption != null)
|
||||
shapeshiftFormByModel.Add(customizationOption.ChrModelID, Tuple.Create(customizationOption.Id, (byte)customizationDisplayInfo.ShapeshiftFormID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MultiMap<uint, ChrCustomizationOptionRecord> customizationOptionsByModel = new MultiMap<uint, ChrCustomizationOptionRecord>();
|
||||
foreach (ChrCustomizationOptionRecord customizationOption in CliDB.ChrCustomizationOptionStorage.Values)
|
||||
customizationOptionsByModel.Add(customizationOption.ChrModelID, customizationOption);
|
||||
|
||||
foreach (ChrCustomizationReqChoiceRecord reqChoice in CliDB.ChrCustomizationReqChoiceStorage.Values)
|
||||
{
|
||||
ChrCustomizationChoiceRecord customizationChoice = CliDB.ChrCustomizationChoiceStorage.LookupByKey(reqChoice.ChrCustomizationChoiceID);
|
||||
if (customizationChoice != null)
|
||||
{
|
||||
if (!_chrCustomizationRequiredChoices.ContainsKey(reqChoice.ChrCustomizationReqID))
|
||||
_chrCustomizationRequiredChoices[reqChoice.ChrCustomizationReqID] = new MultiMap<uint, uint>();
|
||||
|
||||
_chrCustomizationRequiredChoices[reqChoice.ChrCustomizationReqID].Add(customizationChoice.ChrCustomizationOptionID, reqChoice.ChrCustomizationChoiceID);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ChrRaceXChrModelRecord raceModel in CliDB.ChrRaceXChrModelStorage.Values)
|
||||
{
|
||||
ChrModelRecord model = CliDB.ChrModelStorage.LookupByKey(raceModel.ChrModelID);
|
||||
if (model != null)
|
||||
{
|
||||
_chrModelsByRaceAndGender[Tuple.Create((byte)raceModel.ChrRacesID, (byte)model.Sex)] = model;
|
||||
|
||||
var customizationOptionsForModel = customizationOptionsByModel.LookupByKey(model.Id);
|
||||
if (customizationOptionsForModel != null)
|
||||
_chrCustomizationOptionsByRaceAndGender.AddRange(Tuple.Create((byte)raceModel.ChrRacesID, (byte)model.Sex), customizationOptionsForModel);
|
||||
|
||||
// link shapeshift displays to race/gender/form
|
||||
foreach (var shapeshiftOptionsForModel in shapeshiftFormByModel.LookupByKey(model.Id))
|
||||
{
|
||||
ShapeshiftFormModelData data = _chrCustomizationChoicesForShapeshifts[Tuple.Create((byte)raceModel.ChrRacesID, (byte)model.Sex, shapeshiftOptionsForModel.Item2)];
|
||||
data.OptionID = shapeshiftOptionsForModel.Item2;
|
||||
data.Choices = _chrCustomizationChoicesByOption.LookupByKey(shapeshiftOptionsForModel.Item2);
|
||||
if (!data.Choices.Empty())
|
||||
{
|
||||
for (int i = 0; i < data.Choices.Count; ++i)
|
||||
data.Displays[i] = displayInfoByCustomizationChoice.LookupByKey(data.Choices[i].Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (ChrSpecializationRecord chrSpec in CliDB.ChrSpecializationStorage.Values)
|
||||
{
|
||||
//ASSERT(chrSpec.ClassID < MAX_CLASSES);
|
||||
@@ -190,9 +221,6 @@ namespace Game.DataStorage
|
||||
_chrSpecializationsByIndex[storageIndex] = new ChrSpecializationRecord[PlayerConst.MaxSpecializations];
|
||||
|
||||
_chrSpecializationsByIndex[storageIndex][chrSpec.OrderIndex] = chrSpec;
|
||||
|
||||
if (chrSpec.Flags.HasAnyFlag(ChrSpecializationFlag.Recommended))
|
||||
_defaultChrSpecializationsByClass[(uint)chrSpec.ClassID] = chrSpec;
|
||||
}
|
||||
|
||||
foreach (ContentTuningXExpectedRecord contentTuningXExpectedStat in CliDB.ContentTuningXExpectedStorage.Values)
|
||||
@@ -557,7 +585,7 @@ namespace Game.DataStorage
|
||||
UiMapRecord parentUiMap = CliDB.UiMapStorage.LookupByKey(uiMap.ParentUiMapID);
|
||||
if (parentUiMap != null)
|
||||
{
|
||||
if (Convert.ToBoolean(parentUiMap.Flags & 0x80))
|
||||
if (parentUiMap.GetFlags().HasAnyFlag(UiMapFlag.NoWorldPositions))
|
||||
continue;
|
||||
UiMapAssignmentRecord uiMapAssignment = null;
|
||||
UiMapAssignmentRecord parentUiMapAssignment = null;
|
||||
@@ -744,9 +772,7 @@ namespace Game.DataStorage
|
||||
|
||||
public uint GetEmptyAnimStateID()
|
||||
{
|
||||
return 1484;
|
||||
// TEMP: well... AnimationData.db2 in 8.3.0 has more rows than max hardcoded anim id in client
|
||||
// return sAnimationDataStore.GetNumRows();
|
||||
return (uint)CliDB.AnimationDataStorage.Count;
|
||||
}
|
||||
|
||||
public List<uint> GetAreasForGroup(uint areaGroupId)
|
||||
@@ -855,31 +881,6 @@ namespace Game.DataStorage
|
||||
return broadcastText.Text[SharedConst.DefaultLocale];
|
||||
}
|
||||
|
||||
public bool HasCharacterFacialHairStyle(Race race, Gender gender, uint variationId)
|
||||
{
|
||||
return _characterFacialHairStyles.Contains(Tuple.Create((byte)race, (byte)gender, variationId));
|
||||
}
|
||||
|
||||
public bool HasCharSections(Race race, Gender gender, CharBaseSectionVariation variation)
|
||||
{
|
||||
return _charSections.ContainsKey(Tuple.Create((byte)race, (byte)gender, variation));
|
||||
}
|
||||
|
||||
public CharSectionsRecord GetCharSectionEntry(Race race, Gender gender, CharBaseSectionVariation variation, byte variationIndex, byte colorIndex)
|
||||
{
|
||||
var list = _charSections.LookupByKey(Tuple.Create((byte)race, (byte)gender, variation));
|
||||
foreach (var charSection in list)
|
||||
if (charSection.VariationIndex == variationIndex && charSection.ColorIndex == colorIndex)
|
||||
return charSection;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public CharStartOutfitRecord GetCharStartOutfitEntry(uint race, uint class_, uint gender)
|
||||
{
|
||||
return _charStartOutfits.LookupByKey(race | (class_ << 8) | (gender << 16));
|
||||
}
|
||||
|
||||
public string GetClassName(Class class_, Locale locale = Locale.enUS)
|
||||
{
|
||||
ChrClassesRecord classEntry = CliDB.ChrClassesStorage.LookupByKey(class_);
|
||||
@@ -897,6 +898,26 @@ namespace Game.DataStorage
|
||||
return _powersByClass[(int)classId][(int)powerType];
|
||||
}
|
||||
|
||||
public List<ChrCustomizationChoiceRecord> GetCustomiztionChoices(uint chrCustomizationOptionId)
|
||||
{
|
||||
return _chrCustomizationChoicesByOption.LookupByKey(chrCustomizationOptionId);
|
||||
}
|
||||
|
||||
public List<ChrCustomizationOptionRecord> GetCustomiztionOptions(Race race, Gender gender)
|
||||
{
|
||||
return _chrCustomizationOptionsByRaceAndGender.LookupByKey(Tuple.Create(race, gender));
|
||||
}
|
||||
|
||||
public MultiMap<uint, uint> GetRequiredCustomizationChoices(uint chrCustomizationReqId)
|
||||
{
|
||||
return _chrCustomizationRequiredChoices.LookupByKey(chrCustomizationReqId);
|
||||
}
|
||||
|
||||
public ChrModelRecord GetChrModel(Race race, Gender gender)
|
||||
{
|
||||
return _chrModelsByRaceAndGender.LookupByKey(Tuple.Create(race, gender));
|
||||
}
|
||||
|
||||
public string GetChrRaceName(Race race, Locale locale = Locale.enUS)
|
||||
{
|
||||
ChrRacesRecord raceEntry = CliDB.ChrRacesStorage.LookupByKey(race);
|
||||
@@ -916,7 +937,46 @@ namespace Game.DataStorage
|
||||
|
||||
public ChrSpecializationRecord GetDefaultChrSpecializationForClass(Class class_)
|
||||
{
|
||||
return _defaultChrSpecializationsByClass.LookupByKey(class_);
|
||||
return GetChrSpecializationByIndex(class_, PlayerConst.InitialSpecializationIndex);
|
||||
}
|
||||
|
||||
public ContentTuningLevels? GetContentTuningData(uint contentTuningId, uint replacementConditionMask, bool forItem = false)
|
||||
{
|
||||
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(contentTuningId);
|
||||
if (contentTuning == null)
|
||||
return null;
|
||||
|
||||
if (forItem && contentTuning.GetFlags().HasFlag(ContentTuningFlag.DisabledForItem))
|
||||
return null;
|
||||
|
||||
int getLevelAdjustment(ContentTuningCalcType type) => type switch
|
||||
{
|
||||
ContentTuningCalcType.PlusOne => 1,
|
||||
ContentTuningCalcType.PlusMaxLevelForExpansion => (int)Global.ObjectMgr.GetMaxLevelForExpansion((Expansion)WorldConfig.GetUIntValue(WorldCfg.Expansion)),
|
||||
_ => 0
|
||||
};
|
||||
|
||||
ContentTuningLevels levels = new ContentTuningLevels();
|
||||
levels.MinLevel = (short)(contentTuning.MinLevel + getLevelAdjustment((ContentTuningCalcType)contentTuning.MinLevelType));
|
||||
levels.MaxLevel = (short)(contentTuning.MaxLevel + getLevelAdjustment((ContentTuningCalcType)contentTuning.MaxLevelType));
|
||||
levels.MinLevelWithDelta = (short)Math.Clamp(levels.MinLevel + contentTuning.TargetLevelDelta, 1, SharedConst.MaxLevel);
|
||||
levels.MaxLevelWithDelta = (short)Math.Clamp(levels.MaxLevel + contentTuning.TargetLevelMaxDelta, 1, SharedConst.MaxLevel);
|
||||
|
||||
// clamp after calculating levels with delta (delta can bring "overflown" level back into correct range)
|
||||
levels.MinLevel = (short)Math.Clamp((int)levels.MinLevel, 1, SharedConst.MaxLevel);
|
||||
levels.MaxLevel = (short)Math.Clamp((int)levels.MaxLevel, 1, SharedConst.MaxLevel);
|
||||
|
||||
if (contentTuning.TargetLevelMin != 0)
|
||||
levels.TargetLevelMin = (short)contentTuning.TargetLevelMin;
|
||||
else
|
||||
levels.TargetLevelMin = levels.MinLevelWithDelta;
|
||||
|
||||
if (contentTuning.TargetLevelMax != 0)
|
||||
levels.TargetLevelMax = (short)contentTuning.TargetLevelMax;
|
||||
else
|
||||
levels.TargetLevelMax = levels.MaxLevelWithDelta;
|
||||
|
||||
return levels;
|
||||
}
|
||||
|
||||
public string GetCreatureFamilyPetName(CreatureFamily petfamily, Locale locale)
|
||||
@@ -1708,6 +1768,11 @@ namespace Game.DataStorage
|
||||
return _rewardPackItems.LookupByKey(rewardPackID);
|
||||
}
|
||||
|
||||
public ShapeshiftFormModelData GetShapeshiftFormModelData(Race race, Gender gender, ShapeShiftForm form)
|
||||
{
|
||||
return _chrCustomizationChoicesForShapeshifts.LookupByKey(Tuple.Create((byte)race, (byte)gender, (byte)form));
|
||||
}
|
||||
|
||||
public List<SkillLineRecord> GetSkillLinesForParentSkill(uint parentSkillId)
|
||||
{
|
||||
return _skillLinesByParentSkillLine.LookupByKey(parentSkillId);
|
||||
@@ -2091,12 +2156,13 @@ namespace Game.DataStorage
|
||||
MultiMap<uint, AzeritePowerSetMemberRecord> _azeritePowers = new MultiMap<uint, AzeritePowerSetMemberRecord>();
|
||||
Dictionary<(uint azeriteUnlockSetId, ItemContext itemContext), byte[]> _azeriteTierUnlockLevels = new Dictionary<(uint azeriteUnlockSetId, ItemContext itemContext), byte[]>();
|
||||
Dictionary<(uint itemId, ItemContext itemContext), AzeriteUnlockMappingRecord> _azeriteUnlockMappings = new Dictionary<(uint itemId, ItemContext itemContext), AzeriteUnlockMappingRecord>();
|
||||
List<Tuple<byte, byte, uint>> _characterFacialHairStyles = new List<Tuple<byte, byte, uint>>();
|
||||
MultiMap<Tuple<byte, byte, CharBaseSectionVariation>, CharSectionsRecord> _charSections = new MultiMap<Tuple<byte, byte, CharBaseSectionVariation>, CharSectionsRecord>();
|
||||
Dictionary<uint, CharStartOutfitRecord> _charStartOutfits = new Dictionary<uint, CharStartOutfitRecord>();
|
||||
uint[][] _powersByClass = new uint[(int)Class.Max][];
|
||||
MultiMap<uint, ChrCustomizationChoiceRecord> _chrCustomizationChoicesByOption = new MultiMap<uint, ChrCustomizationChoiceRecord>();
|
||||
Dictionary<Tuple<byte, byte>, ChrModelRecord> _chrModelsByRaceAndGender = new Dictionary<Tuple<byte, byte>, ChrModelRecord>();
|
||||
Dictionary<Tuple<byte, byte, byte>, ShapeshiftFormModelData> _chrCustomizationChoicesForShapeshifts = new Dictionary<Tuple<byte, byte, byte>, ShapeshiftFormModelData>();
|
||||
MultiMap<Tuple<byte, byte>, ChrCustomizationOptionRecord> _chrCustomizationOptionsByRaceAndGender = new MultiMap<Tuple<byte, byte>, ChrCustomizationOptionRecord>();
|
||||
Dictionary<uint, MultiMap<uint, uint>> _chrCustomizationRequiredChoices = new Dictionary<uint, MultiMap<uint, uint>>();
|
||||
ChrSpecializationRecord[][] _chrSpecializationsByIndex = new ChrSpecializationRecord[(int)Class.Max + 1][];
|
||||
Dictionary<uint, ChrSpecializationRecord> _defaultChrSpecializationsByClass = new Dictionary<uint, ChrSpecializationRecord>();
|
||||
MultiMap<uint, CurvePointRecord> _curvePoints = new MultiMap<uint, CurvePointRecord>();
|
||||
Dictionary<Tuple<uint, byte, byte, byte>, EmotesTextSoundRecord> _emoteTextSounds = new Dictionary<Tuple<uint, byte, byte, byte>, EmotesTextSoundRecord>();
|
||||
Dictionary<Tuple<uint, int>, ExpectedStatRecord> _expectedStatsByLevel = new Dictionary<Tuple<uint, int>, ExpectedStatRecord>();
|
||||
@@ -2363,6 +2429,23 @@ namespace Game.DataStorage
|
||||
}
|
||||
}
|
||||
|
||||
public struct ContentTuningLevels
|
||||
{
|
||||
public short MinLevel;
|
||||
public short MaxLevel;
|
||||
public short MinLevelWithDelta;
|
||||
public short MaxLevelWithDelta;
|
||||
public short TargetLevelMin;
|
||||
public short TargetLevelMax;
|
||||
}
|
||||
|
||||
public class ShapeshiftFormModelData
|
||||
{
|
||||
public uint OptionID;
|
||||
public List<ChrCustomizationChoiceRecord> Choices = new List<ChrCustomizationChoiceRecord>();
|
||||
public List<ChrCustomizationDisplayInfoRecord> Displays = new List<ChrCustomizationDisplayInfoRecord>();
|
||||
}
|
||||
|
||||
enum CurveInterpolationMode
|
||||
{
|
||||
Linear = 0,
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Game.DataStorage
|
||||
public int RewardItemID;
|
||||
public uint CriteriaTree;
|
||||
public ushort SharesCriteria;
|
||||
public int CovenantID;
|
||||
}
|
||||
|
||||
public sealed class AnimationDataRecord
|
||||
@@ -79,7 +80,6 @@ namespace Game.DataStorage
|
||||
public ushort UwAmbience;
|
||||
public ushort ZoneMusic;
|
||||
public ushort UwZoneMusic;
|
||||
public sbyte ExplorationLevel;
|
||||
public ushort IntroSound;
|
||||
public uint UwIntroSound;
|
||||
public byte FactionGroupMask;
|
||||
@@ -89,6 +89,7 @@ namespace Game.DataStorage
|
||||
public byte WildBattlePetLevelMin;
|
||||
public byte WildBattlePetLevelMax;
|
||||
public byte WindSettingsID;
|
||||
public uint ContentTuningID;
|
||||
public AreaFlags[] Flags = new AreaFlags[2];
|
||||
public ushort[] LiquidTypeID = new ushort[4];
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Game.DataStorage
|
||||
public sealed class BattlePetBreedStateRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte BattlePetStateID;
|
||||
public int BattlePetStateID;
|
||||
public ushort Value;
|
||||
public uint BattlePetBreedID;
|
||||
}
|
||||
@@ -72,6 +72,7 @@ namespace Game.DataStorage
|
||||
public sbyte SourceTypeEnum;
|
||||
public int CardUIModelSceneID;
|
||||
public int LoadoutUIModelSceneID;
|
||||
public int CovenantID;
|
||||
}
|
||||
|
||||
public sealed class BattlePetSpeciesStateRecord
|
||||
@@ -100,7 +101,7 @@ namespace Game.DataStorage
|
||||
public ushort HolidayWorldState;
|
||||
public BattlemasterListFlags Flags;
|
||||
public int IconFileDataID;
|
||||
public short RequiredPlayerConditionID;
|
||||
public int RequiredPlayerConditionID;
|
||||
public short[] MapId = new short[16];
|
||||
}
|
||||
|
||||
@@ -109,7 +110,7 @@ namespace Game.DataStorage
|
||||
public LocalizedString Text;
|
||||
public LocalizedString Text1;
|
||||
public uint Id;
|
||||
public byte LanguageID;
|
||||
public int LanguageID;
|
||||
public int ConditionID;
|
||||
public ushort EmotesID;
|
||||
public byte Flags;
|
||||
|
||||
@@ -30,47 +30,6 @@ namespace Game.DataStorage
|
||||
public uint ChallengeOrigin;
|
||||
}
|
||||
|
||||
public sealed class CharacterFacialHairStylesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int[] Geoset = new int[5];
|
||||
public byte RaceID;
|
||||
public byte SexID;
|
||||
public byte VariationID;
|
||||
}
|
||||
|
||||
public sealed class CharBaseSectionRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte LayoutResType;
|
||||
public CharBaseSectionVariation VariationEnum;
|
||||
public byte ResolutionVariationEnum;
|
||||
}
|
||||
|
||||
public sealed class CharSectionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte RaceID;
|
||||
public byte SexID;
|
||||
public sbyte BaseSection;
|
||||
public byte VariationIndex;
|
||||
public byte ColorIndex;
|
||||
public short Flags;
|
||||
public int[] MaterialResourcesID = new int[3];
|
||||
}
|
||||
|
||||
public sealed class CharStartOutfitRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte ClassID;
|
||||
public byte SexID;
|
||||
public byte OutfitID;
|
||||
public uint PetDisplayID; // Pet Model ID for starting pet
|
||||
public byte PetFamilyID; // Pet Family Entry for starting pet
|
||||
public int[] ItemID = new int[24];
|
||||
public uint RaceID;
|
||||
}
|
||||
|
||||
public sealed class CharTitlesRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -80,13 +39,31 @@ namespace Game.DataStorage
|
||||
public sbyte Flags;
|
||||
}
|
||||
|
||||
public sealed class ChatChannelsRecord
|
||||
public sealed class CharacterLoadoutRecord
|
||||
{
|
||||
public long RaceMask;
|
||||
public uint Id;
|
||||
public sbyte ChrClassID;
|
||||
public sbyte Purpose;
|
||||
|
||||
public bool IsForNewCharacter() { return Purpose == 9; }
|
||||
}
|
||||
|
||||
public sealed class CharacterLoadoutItemRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort CharacterLoadoutID;
|
||||
public uint ItemID;
|
||||
}
|
||||
|
||||
public sealed class ChatChannelsRecord
|
||||
{
|
||||
public LocalizedString Name;
|
||||
public string Shortcut;
|
||||
public string Shortcut;
|
||||
public uint Id;
|
||||
public ChannelDBCFlags Flags;
|
||||
public sbyte FactionGroup;
|
||||
public int Ruleset;
|
||||
}
|
||||
|
||||
public sealed class ChrClassesRecord
|
||||
@@ -96,14 +73,29 @@ namespace Game.DataStorage
|
||||
public string NameMale;
|
||||
public string NameFemale;
|
||||
public string PetNameToken;
|
||||
public string Description;
|
||||
public string RoleInfoString;
|
||||
public string DisabledString;
|
||||
public string HyphenatedNameMale;
|
||||
public string HyphenatedNameFemale;
|
||||
public uint Id;
|
||||
public uint CreateScreenFileDataID;
|
||||
public uint SelectScreenFileDataID;
|
||||
public uint IconFileDataID;
|
||||
public uint LowResScreenFileDataID;
|
||||
public int StartingLevel;
|
||||
public uint Flags;
|
||||
public uint SpellTextureBlobFileDataID;
|
||||
public ushort Flags;
|
||||
public uint RolesMask;
|
||||
public uint ArmorTypeMask;
|
||||
public int CharStartKitUnknown901;
|
||||
public int MaleCharacterCreationVisualFallback;
|
||||
public int MaleCharacterCreationIdleVisualFallback;
|
||||
public int FemaleCharacterCreationVisualFallback;
|
||||
public int FemaleCharacterCreationIdleVisualFallback;
|
||||
public int CharacterCreationIdleGroundVisualFallback;
|
||||
public int CharacterCreationGroundVisualFallback;
|
||||
public int AlteredFormCharacterCreationIdleVisualFallback;
|
||||
public int CharacterCreationAnimLoopWaitTimeMsFallback;
|
||||
public ushort CinematicSequenceID;
|
||||
public ushort DefaultSpec;
|
||||
public byte PrimaryStatPriority;
|
||||
@@ -112,6 +104,9 @@ namespace Game.DataStorage
|
||||
public byte AttackPowerPerAgility;
|
||||
public byte AttackPowerPerStrength;
|
||||
public byte SpellClassSet;
|
||||
public byte ChatColorR;
|
||||
public byte ChatColorG;
|
||||
public byte ChatColorB;
|
||||
}
|
||||
|
||||
public sealed class ChrClassesXPowerTypesRecord
|
||||
@@ -121,6 +116,103 @@ namespace Game.DataStorage
|
||||
public uint ClassID;
|
||||
}
|
||||
|
||||
public sealed class ChrCustomizationChoiceRecord
|
||||
{
|
||||
public LocalizedString Name;
|
||||
public uint Id;
|
||||
public uint ChrCustomizationOptionID;
|
||||
public uint ChrCustomizationReqID;
|
||||
public ushort SortOrder;
|
||||
public int SwatchColor1;
|
||||
public int SwatchColor2;
|
||||
public ushort UiOrderIndex;
|
||||
public int Flags;
|
||||
}
|
||||
|
||||
public sealed class ChrCustomizationDisplayInfoRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int ShapeshiftFormID;
|
||||
public uint DisplayID;
|
||||
public float BarberShopMinCameraDistance;
|
||||
public float BarberShopHeightOffset;
|
||||
}
|
||||
|
||||
public sealed class ChrCustomizationElementRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ChrCustomizationChoiceID;
|
||||
public int RelatedChrCustomizationChoiceID;
|
||||
public int ChrCustomizationGeosetID;
|
||||
public int ChrCustomizationSkinnedModelID;
|
||||
public int ChrCustomizationMaterialID;
|
||||
public int ChrCustomizationBoneSetID;
|
||||
public int ChrCustomizationCondModelID;
|
||||
public int ChrCustomizationDisplayInfoID;
|
||||
}
|
||||
|
||||
public sealed class ChrCustomizationOptionRecord
|
||||
{
|
||||
public LocalizedString Name;
|
||||
public uint Id;
|
||||
public ushort SecondaryID;
|
||||
public int Flags;
|
||||
public uint ChrModelID;
|
||||
public int SortIndex;
|
||||
public int ChrCustomizationCategoryID;
|
||||
public int OptionType;
|
||||
public float BarberShopCostModifier;
|
||||
public int ChrCustomizationID;
|
||||
public int ChrCustomizationReqID;
|
||||
public int UiOrderIndex;
|
||||
}
|
||||
|
||||
public sealed class ChrCustomizationReqRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int Flags;
|
||||
public int ClassMask;
|
||||
public int AchievementID;
|
||||
public int OverrideArchive; // -1: allow any, otherwise must match OverrideArchive cvar
|
||||
public uint ItemModifiedAppearanceID;
|
||||
|
||||
public ChrCustomizationReqFlag GetFlags() { return (ChrCustomizationReqFlag)Flags; }
|
||||
}
|
||||
|
||||
public sealed class ChrCustomizationReqChoiceRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ChrCustomizationChoiceID;
|
||||
public uint ChrCustomizationReqID;
|
||||
}
|
||||
|
||||
public sealed class ChrModelRecord
|
||||
{
|
||||
public float[] FaceCustomizationOffset = new float[3];
|
||||
public float[] CustomizeOffset = new float[3];
|
||||
public uint Id;
|
||||
public int Sex;
|
||||
public uint DisplayID;
|
||||
public int CharComponentTextureLayoutID;
|
||||
public int Flags;
|
||||
public int SkeletonFileDataID;
|
||||
public int ModelFallbackChrModelID;
|
||||
public int TextureFallbackChrModelID;
|
||||
public int HelmVisFallbackChrModelID;
|
||||
public float CustomizeScale;
|
||||
public float CustomizeFacing;
|
||||
public float CameraDistanceOffset;
|
||||
public float BarberShopCameraOffsetScale;
|
||||
public float BarberShopCameraRotationOffset;
|
||||
}
|
||||
|
||||
public sealed class ChrRaceXChrModelRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int ChrRacesID;
|
||||
public int ChrModelID;
|
||||
}
|
||||
|
||||
public sealed class ChrRacesRecord
|
||||
{
|
||||
public string ClientPrefix;
|
||||
@@ -129,37 +221,39 @@ namespace Game.DataStorage
|
||||
public string NameFemale;
|
||||
public string NameLowercase;
|
||||
public string NameFemaleLowercase;
|
||||
public string NameS;
|
||||
public string NameFemaleS;
|
||||
public string NameLowercaseS;
|
||||
public string NameFemaleLowercaseS;
|
||||
public string RaceFantasyDescription;
|
||||
public string NameL;
|
||||
public string NameFemaleL;
|
||||
public string NameLowercaseL;
|
||||
public string NameFemaleLowercaseL;
|
||||
public uint Id;
|
||||
public int Flags;
|
||||
public uint MaleDisplayId;
|
||||
public uint FemaleDisplayId;
|
||||
public uint HighResMaleDisplayId;
|
||||
public uint HighResFemaleDisplayId;
|
||||
public int BaseLanguage;
|
||||
public int ResSicknessSpellID;
|
||||
public int SplashSoundID;
|
||||
public int CreateScreenFileDataID;
|
||||
public int SelectScreenFileDataID;
|
||||
public float[] MaleCustomizeOffset = new float[3];
|
||||
public float[] FemaleCustomizeOffset = new float[3];
|
||||
public int LowResScreenFileDataID;
|
||||
public uint[] AlteredFormStartVisualKitID = new uint[3];
|
||||
public uint[] AlteredFormFinishVisualKitID = new uint[3];
|
||||
public int HeritageArmorAchievementID;
|
||||
public int StartingLevel;
|
||||
public int UiDisplayOrder;
|
||||
public int FemaleSkeletonFileDataID;
|
||||
public int MaleSkeletonFileDataID;
|
||||
public int HelmVisFallbackRaceID;
|
||||
public int PlayableRaceBit;
|
||||
public int HelmetAnimScalingRaceID;
|
||||
public int TransmogrifyDisabledSlotMask;
|
||||
public float[] AlteredFormCustomizeOffsetFallback = new float[3];
|
||||
public float AlteredFormCustomizeRotationFallback;
|
||||
public ushort FactionID;
|
||||
public ushort CinematicSequenceID;
|
||||
public short ResSicknessSpellID;
|
||||
public short SplashSoundID;
|
||||
public sbyte BaseLanguage;
|
||||
public sbyte CreatureType;
|
||||
public sbyte Alliance;
|
||||
public sbyte RaceRelated;
|
||||
public sbyte UnalteredVisualRaceID;
|
||||
public sbyte CharComponentTextureLayoutID;
|
||||
public sbyte CharComponentTexLayoutHiResID;
|
||||
public sbyte DefaultClassID;
|
||||
public sbyte NeutralRaceID;
|
||||
public sbyte MaleModelFallbackRaceID;
|
||||
@@ -170,6 +264,7 @@ namespace Game.DataStorage
|
||||
public sbyte MaleTextureFallbackSex;
|
||||
public sbyte FemaleTextureFallbackRaceID;
|
||||
public sbyte FemaleTextureFallbackSex;
|
||||
public sbyte UnalteredVisualCustomizationRaceID;
|
||||
}
|
||||
|
||||
public sealed class ChrSpecializationRecord
|
||||
@@ -213,10 +308,31 @@ namespace Game.DataStorage
|
||||
public sealed class ContentTuningRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int MinLevel;
|
||||
public int MaxLevel;
|
||||
public int Flags;
|
||||
public int ExpansionID;
|
||||
public int MinLevel;
|
||||
public int MaxLevel;
|
||||
public int MinLevelType;
|
||||
public int MaxLevelType;
|
||||
public int TargetLevelDelta;
|
||||
public int TargetLevelMaxDelta;
|
||||
public int TargetLevelMin;
|
||||
public int TargetLevelMax;
|
||||
public int MinItemLevel;
|
||||
|
||||
public ContentTuningFlag GetFlags() { return (ContentTuningFlag)Flags; }
|
||||
|
||||
public int GetScalingFactionGroup()
|
||||
{
|
||||
ContentTuningFlag flags = GetFlags();
|
||||
if (flags.HasFlag(ContentTuningFlag.Horde))
|
||||
return 5;
|
||||
|
||||
if (flags.HasFlag(ContentTuningFlag.Alliance))
|
||||
return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContentTuningXExpectedRecord
|
||||
@@ -284,15 +400,9 @@ namespace Game.DataStorage
|
||||
public sbyte DisplayRaceID;
|
||||
public sbyte DisplaySexID;
|
||||
public sbyte DisplayClassID;
|
||||
public sbyte SkinID;
|
||||
public sbyte FaceID;
|
||||
public sbyte HairStyleID;
|
||||
public sbyte HairColorID;
|
||||
public sbyte FacialHairID;
|
||||
public sbyte Flags;
|
||||
public int BakeMaterialResourcesID;
|
||||
public int HDBakeMaterialResourcesID;
|
||||
public byte[] CustomDisplayOption = new byte[3];
|
||||
}
|
||||
|
||||
public sealed class CreatureFamilyRecord
|
||||
@@ -385,18 +495,19 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string Description;
|
||||
public byte CategoryID;
|
||||
public int CategoryID;
|
||||
public int InventoryIconFileID;
|
||||
public uint SpellWeight;
|
||||
public byte SpellCategory;
|
||||
public uint MaxQty;
|
||||
public uint MaxEarnablePerWeek;
|
||||
public uint Flags;
|
||||
public sbyte Quality;
|
||||
public int FactionID;
|
||||
public int ItemGroupSoundsID;
|
||||
public int ConvertToPlayerExperience;
|
||||
public int PlayerConditionID;
|
||||
public int XpQuestDifficulty;
|
||||
public int AwardConditionID;
|
||||
public int MaxQtyWorldStateID;
|
||||
public int[] Flags = new int[2];
|
||||
}
|
||||
|
||||
public sealed class CurveRecord
|
||||
@@ -410,6 +521,7 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public Vector2 Pos;
|
||||
public Vector2 PosPreSquish;
|
||||
public ushort CurveID;
|
||||
public byte OrderIndex;
|
||||
}
|
||||
|
||||
@@ -24,20 +24,20 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public sbyte State0ImpactEffectDoodadSet;
|
||||
public byte State0AmbientDoodadSet;
|
||||
public ushort State1Wmo;
|
||||
public uint State1Wmo;
|
||||
public sbyte State1DestructionDoodadSet;
|
||||
public sbyte State1ImpactEffectDoodadSet;
|
||||
public byte State1AmbientDoodadSet;
|
||||
public ushort State2Wmo;
|
||||
public uint State2Wmo;
|
||||
public sbyte State2DestructionDoodadSet;
|
||||
public sbyte State2ImpactEffectDoodadSet;
|
||||
public byte State2AmbientDoodadSet;
|
||||
public ushort State3Wmo;
|
||||
public uint State3Wmo;
|
||||
public byte State3InitDoodadSet;
|
||||
public byte State3AmbientDoodadSet;
|
||||
public byte EjectDirection;
|
||||
public byte DoNotHighlight;
|
||||
public ushort State0Wmo;
|
||||
public uint State0Wmo;
|
||||
public byte HealEffect;
|
||||
public ushort HealEffectSpeed;
|
||||
public byte State0NameSet;
|
||||
@@ -69,7 +69,7 @@ namespace Game.DataStorage
|
||||
public LocalizedString Name;
|
||||
public uint Id;
|
||||
public short MapID;
|
||||
public sbyte DifficultyID;
|
||||
public int DifficultyID;
|
||||
public int OrderIndex;
|
||||
public int CompleteWorldStateID;
|
||||
public sbyte Bit;
|
||||
|
||||
@@ -47,13 +47,13 @@ namespace Game.DataStorage
|
||||
public Vector3 Pos;
|
||||
public float[] Rot = new float[4];
|
||||
public uint Id;
|
||||
public ushort OwnerID;
|
||||
public ushort DisplayID;
|
||||
public uint OwnerID;
|
||||
public uint DisplayID;
|
||||
public float Scale;
|
||||
public GameObjectTypes TypeID;
|
||||
public byte PhaseUseFlags;
|
||||
public ushort PhaseID;
|
||||
public ushort PhaseGroupID;
|
||||
public int PhaseUseFlags;
|
||||
public int PhaseID;
|
||||
public int PhaseGroupID;
|
||||
public int[] PropValue = new int[8];
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Game.DataStorage
|
||||
public byte BuildingType;
|
||||
public uint HordeGameObjectID;
|
||||
public uint AllianceGameObjectID;
|
||||
public byte GarrSiteID;
|
||||
public int GarrSiteID;
|
||||
public byte UpgradeLevel;
|
||||
public int BuildSeconds;
|
||||
public ushort CurrencyTypeID;
|
||||
@@ -153,6 +153,8 @@ namespace Game.DataStorage
|
||||
public byte ChrClassID;
|
||||
public byte Flags;
|
||||
public byte Gender;
|
||||
public int AutoCombatantID;
|
||||
public int CovenantID;
|
||||
}
|
||||
|
||||
public sealed class GarrFollowerXAbilityRecord
|
||||
@@ -218,7 +220,6 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public ushort EnchantId;
|
||||
public SocketColor Type;
|
||||
public ushort MinItemLevel;
|
||||
}
|
||||
|
||||
public sealed class GlyphBindableSpellRecord
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace Game.DataStorage
|
||||
public sbyte SoundOverrideSubclassID;
|
||||
public int IconFileDataID;
|
||||
public byte ItemGroupSoundsID;
|
||||
public int ModifiedCraftingReagentItemID;
|
||||
}
|
||||
|
||||
public sealed class ItemAppearanceRecord
|
||||
@@ -66,6 +67,7 @@ namespace Game.DataStorage
|
||||
public uint ItemDisplayInfoID;
|
||||
public int DefaultIconFileDataID;
|
||||
public int UiOrder;
|
||||
public int PlayerConditionID;
|
||||
}
|
||||
|
||||
public sealed class ItemArmorQualityRecord
|
||||
@@ -100,7 +102,7 @@ namespace Game.DataStorage
|
||||
public sealed class ItemBonusRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int[] Value = new int[3];
|
||||
public int[] Value = new int[4];
|
||||
public ushort ParentItemBonusListID;
|
||||
public ItemBonusType BonusType;
|
||||
public byte OrderIndex;
|
||||
@@ -109,11 +111,12 @@ namespace Game.DataStorage
|
||||
public sealed class ItemBonusListGroupEntryRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int ItemBonusListGroupID;
|
||||
public int ItemBonusListID;
|
||||
public int ItemLevelSelectorID;
|
||||
public int OrderIndex;
|
||||
public int ItemExtendedCostID;
|
||||
public int ItemBonusListGroupID;
|
||||
public int PlayerConditionID;
|
||||
}
|
||||
|
||||
public sealed class ItemBonusListLevelDeltaRecord
|
||||
@@ -345,6 +348,9 @@ namespace Game.DataStorage
|
||||
public float PriceRandomValue;
|
||||
public int[] Flags = new int[4];
|
||||
public int FactionRelated;
|
||||
public int ModifiedCraftingReagentItemID;
|
||||
public uint ContentTuningID;
|
||||
public uint PlayerLevelToItemLevelCurveID;
|
||||
public ushort ItemNameDescriptionID;
|
||||
public ushort RequiredTransmogHoliday;
|
||||
public ushort RequiredHoliday;
|
||||
@@ -359,7 +365,6 @@ namespace Game.DataStorage
|
||||
public ushort StartQuestID;
|
||||
public ushort PageID;
|
||||
public ushort ItemDelay;
|
||||
public ushort ScalingStatDistributionID;
|
||||
public ushort MinFactionID;
|
||||
public ushort RequiredSkillRank;
|
||||
public ushort RequiredSkill;
|
||||
|
||||
@@ -25,8 +25,6 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public LocalizedString Name;
|
||||
public string Description;
|
||||
public byte MinLevel;
|
||||
public ushort MaxLevel;
|
||||
public LfgType TypeID;
|
||||
public byte Subtype;
|
||||
public sbyte Faction;
|
||||
@@ -40,9 +38,6 @@ namespace Game.DataStorage
|
||||
public byte GroupID;
|
||||
public byte OrderIndex;
|
||||
public uint RequiredPlayerConditionId;
|
||||
public byte TargetLevel;
|
||||
public byte TargetLevelMin;
|
||||
public ushort TargetLevelMax;
|
||||
public ushort RandomID;
|
||||
public ushort ScenarioID;
|
||||
public ushort FinalEncounterID;
|
||||
@@ -55,6 +50,7 @@ namespace Game.DataStorage
|
||||
public ushort BonusReputationAmount;
|
||||
public ushort MentorItemLevel;
|
||||
public byte MentorCharLevel;
|
||||
public uint ContentTuningID;
|
||||
public LfgFlags[] Flags = new LfgFlags[2];
|
||||
|
||||
// Helpers
|
||||
@@ -100,6 +96,7 @@ namespace Game.DataStorage
|
||||
public sealed class LockRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int Flags;
|
||||
public int[] Index = new int[SharedConst.MaxLockCase];
|
||||
public ushort[] Skill = new ushort[SharedConst.MaxLockCase];
|
||||
public byte[] LockType = new byte[SharedConst.MaxLockCase];
|
||||
|
||||
@@ -30,6 +30,7 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string Directory;
|
||||
public LocalizedString MapName;
|
||||
public string InternalName;
|
||||
public string MapDescription0; // Horde
|
||||
public string MapDescription1; // Alliance
|
||||
public string PvpShortDescription;
|
||||
|
||||
@@ -37,11 +37,9 @@ namespace Game.DataStorage
|
||||
public long RaceMask;
|
||||
public string FailureDescription;
|
||||
public uint Id;
|
||||
public ushort MinLevel;
|
||||
public ushort MaxLevel;
|
||||
public int ClassMask;
|
||||
public uint SkillLogic;
|
||||
public byte LanguageID;
|
||||
public int LanguageID;
|
||||
public byte MinLanguage;
|
||||
public int MaxLanguage;
|
||||
public ushort MaxFactionID;
|
||||
@@ -57,7 +55,7 @@ namespace Game.DataStorage
|
||||
public byte ItemFlags;
|
||||
public uint AuraSpellLogic;
|
||||
public ushort WorldStateExpressionID;
|
||||
public byte WeatherID;
|
||||
public int WeatherID;
|
||||
public byte PartyStatus;
|
||||
public byte LifetimeMaxPVPRank;
|
||||
public uint AchievementLogic;
|
||||
@@ -66,7 +64,7 @@ namespace Game.DataStorage
|
||||
public uint AreaLogic;
|
||||
public uint LfgLogic;
|
||||
public uint CurrencyLogic;
|
||||
public ushort QuestKillID;
|
||||
public uint QuestKillID;
|
||||
public uint QuestKillLogic;
|
||||
public sbyte MinExpansionLevel;
|
||||
public sbyte MaxExpansionLevel;
|
||||
@@ -77,7 +75,7 @@ namespace Game.DataStorage
|
||||
public byte PhaseUseFlags;
|
||||
public ushort PhaseID;
|
||||
public uint PhaseGroupID;
|
||||
public byte Flags;
|
||||
public int Flags;
|
||||
public sbyte ChrSpecializationIndex;
|
||||
public sbyte ChrSpecializationRole;
|
||||
public uint ModifierTreeID;
|
||||
@@ -91,14 +89,16 @@ namespace Game.DataStorage
|
||||
public sbyte MinExpansionTier;
|
||||
public byte MinPVPRank;
|
||||
public byte MaxPVPRank;
|
||||
public uint ContentTuningID;
|
||||
public int CovenantID;
|
||||
public ushort[] SkillID = new ushort[4];
|
||||
public ushort[] MinSkill = new ushort[4];
|
||||
public ushort[] MaxSkill = new ushort[4];
|
||||
public uint[] MinFactionID = new uint[3];
|
||||
public byte[] MinReputation = new byte[3];
|
||||
public ushort[] PrevQuestID = new ushort[4];
|
||||
public ushort[] CurrQuestID = new ushort[4];
|
||||
public ushort[] CurrentCompletedQuestID = new ushort[4];
|
||||
public uint[] PrevQuestID = new uint[4];
|
||||
public uint[] CurrQuestID = new uint[4];
|
||||
public uint[] CurrentCompletedQuestID = new uint[4];
|
||||
public uint[] SpellID = new uint[4];
|
||||
public uint[] ItemID = new uint[4];
|
||||
public uint[] ItemCount = new uint[4];
|
||||
|
||||
@@ -21,14 +21,6 @@ using System;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
public sealed class ScalingStatDistributionRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort PlayerLevelToItemLevelCurveID;
|
||||
public int MinLevel;
|
||||
public int MaxLevel;
|
||||
}
|
||||
|
||||
public sealed class ScenarioRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -46,7 +38,7 @@ namespace Game.DataStorage
|
||||
public string Title;
|
||||
public ushort ScenarioID;
|
||||
public uint CriteriaTreeId;
|
||||
public ushort RewardQuestID;
|
||||
public uint RewardQuestID;
|
||||
public int RelatedStep; // Bonus step can only be completed if scenario is in the step specified in this field
|
||||
public ushort Supersedes; // Used in conjunction with Proving Grounds scenarios, when sequencing steps (Not using step order?)
|
||||
public byte OrderIndex;
|
||||
@@ -117,7 +109,7 @@ namespace Game.DataStorage
|
||||
public AbilityLearnType AcquireMethod;
|
||||
public ushort TrivialSkillLineRankHigh;
|
||||
public ushort TrivialSkillLineRankLow;
|
||||
public sbyte Flags;
|
||||
public int Flags;
|
||||
public byte NumSkillUps;
|
||||
public short UniqueBit;
|
||||
public short TradeSkillCategoryID;
|
||||
@@ -205,7 +197,6 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public int Base;
|
||||
public short PerLevel;
|
||||
public int Minimum;
|
||||
}
|
||||
|
||||
@@ -269,7 +260,6 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public int Duration;
|
||||
public uint DurationPerLevel;
|
||||
public int MaxDuration;
|
||||
}
|
||||
|
||||
@@ -333,14 +323,16 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class SpellItemEnchantmentRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string HordeName;
|
||||
public uint Id;
|
||||
public uint[] EffectArg = new uint[ItemConst.MaxItemEnchantmentEffects];
|
||||
public float[] EffectScalingPoints = new float[ItemConst.MaxItemEnchantmentEffects];
|
||||
public uint TransmogPlayerConditionID;
|
||||
public uint TransmogCost;
|
||||
public uint IconFileDataID;
|
||||
public int MinItemLevel;
|
||||
public int MaxItemLevel;
|
||||
public uint TransmogUseConditionID;
|
||||
public uint TransmogCost;
|
||||
public ushort[] EffectPointsMin = new ushort[ItemConst.MaxItemEnchantmentEffects];
|
||||
public ushort ItemVisual;
|
||||
public EnchantmentSlotMask Flags;
|
||||
@@ -379,17 +371,17 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public ushort BaseLevel;
|
||||
public ushort MaxLevel;
|
||||
public ushort SpellLevel;
|
||||
public byte MaxPassiveAuraLevel;
|
||||
public ushort BaseLevel;
|
||||
public ushort SpellLevel;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
public sealed class SpellMiscRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int[] Attributes = new int[14];
|
||||
public int[] Attributes = new int[15];
|
||||
public byte DifficultyID;
|
||||
public ushort CastingTimeIndex;
|
||||
public ushort DurationIndex;
|
||||
@@ -401,6 +393,9 @@ namespace Game.DataStorage
|
||||
public uint SpellIconFileDataID;
|
||||
public uint ActiveIconFileDataID;
|
||||
public uint ContentTuningID;
|
||||
public int ShowFutureSpellPlayerConditionID;
|
||||
public int SpellVisualScript;
|
||||
public int ActiveSpellVisualScript;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
@@ -447,7 +442,7 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public SpellProcsPerMinuteModType Type;
|
||||
public ushort Param;
|
||||
public uint Param;
|
||||
public float Coeff;
|
||||
public uint SpellProcsPerMinuteID;
|
||||
}
|
||||
@@ -550,7 +545,6 @@ namespace Game.DataStorage
|
||||
public byte DifficultyID;
|
||||
public uint SpellVisualID;
|
||||
public float Probability;
|
||||
public byte Flags;
|
||||
public byte Priority;
|
||||
public int SpellIconFileID;
|
||||
public int ActiveIconFileID;
|
||||
|
||||
@@ -103,6 +103,15 @@ namespace Game.DataStorage
|
||||
public int RequiredTransmogHoliday;
|
||||
}
|
||||
|
||||
public sealed class TransmogIllusionRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int UnlockConditionID;
|
||||
public int TransmogCost;
|
||||
public int SpellItemEnchantmentID;
|
||||
public int Flags;
|
||||
}
|
||||
|
||||
public sealed class TransmogSetRecord
|
||||
{
|
||||
public string Name;
|
||||
|
||||
@@ -27,15 +27,16 @@ namespace Game.DataStorage
|
||||
public int Flags;
|
||||
public int System;
|
||||
public UiMapType Type;
|
||||
public uint LevelRangeMin;
|
||||
public uint LevelRangeMax;
|
||||
public int BountySetID;
|
||||
public uint BountyDisplayLocation;
|
||||
public int VisibilityPlayerConditionID;
|
||||
public sbyte HelpTextPosition;
|
||||
public int BkgAtlasID;
|
||||
public int AlternateUiMapGroup;
|
||||
}
|
||||
public int ContentTuningID;
|
||||
|
||||
public UiMapFlag GetFlags() { return (UiMapFlag)Flags; }
|
||||
}
|
||||
|
||||
public sealed class UiMapAssignmentRecord
|
||||
{
|
||||
@@ -61,6 +62,7 @@ namespace Game.DataStorage
|
||||
public int ChildUiMapID;
|
||||
public int OverrideHighlightFileDataID;
|
||||
public int OverrideHighlightAtlasID;
|
||||
public int Flags;
|
||||
}
|
||||
|
||||
public sealed class UiMapXMapArtRecord
|
||||
|
||||
@@ -37,9 +37,9 @@ namespace Game.DataStorage
|
||||
public float FacingLimitRight;
|
||||
public float FacingLimitLeft;
|
||||
public float CameraYawOffset;
|
||||
public byte UiLocomotionType;
|
||||
public ushort VehicleUIIndicatorID;
|
||||
public int MissileTargetingID;
|
||||
public ushort VehiclePOITypeID;
|
||||
public ushort[] SeatID = new ushort[8];
|
||||
public ushort[] PowerDisplayID = new ushort[3];
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Game.DataStorage
|
||||
guildGuid = guild.GetGUID();
|
||||
|
||||
_whoListStorage.Add(new WhoListPlayerInfo(player.GetGUID(), player.GetTeam(), player.GetSession().GetSecurity(), player.GetLevel(),
|
||||
player.GetClass(), player.GetRace(), player.GetZoneId(), player.m_playerData.NativeSex, player.IsVisible(),
|
||||
player.GetClass(), player.GetRace(), player.GetZoneId(), (byte)player.GetNativeSex(), player.IsVisible(),
|
||||
player.IsGameMaster(), playerName, guildName, guildGuid));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1535,10 +1535,6 @@ namespace Game.DungeonFinding
|
||||
lockStatus = LfgLockStatusType.RaidLocked;
|
||||
else if (dungeon.difficulty > Difficulty.Normal && player.GetBoundInstance(dungeon.map, dungeon.difficulty) != null)
|
||||
lockStatus = LfgLockStatusType.RaidLocked;
|
||||
else if (dungeon.minlevel > level)
|
||||
lockStatus = LfgLockStatusType.TooLowLevel;
|
||||
else if (dungeon.maxlevel < level)
|
||||
lockStatus = LfgLockStatusType.TooHighLevel;
|
||||
else if (dungeon.seasonal && !IsSeasonActive(dungeon.id))
|
||||
lockStatus = LfgLockStatusType.NotInSeason;
|
||||
else if (dungeon.requiredItemLevel > player.GetAverageItemLevel())
|
||||
@@ -1560,16 +1556,23 @@ namespace Game.DungeonFinding
|
||||
else if (ar.item2 != 0 && !player.HasItemCount(ar.item2))
|
||||
lockStatus = LfgLockStatusType.MissingItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(dungeon.contentTuningId, player.m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (levels.HasValue)
|
||||
{
|
||||
if (levels.Value.MinLevel > level)
|
||||
lockStatus = LfgLockStatusType.TooLowLevel;
|
||||
if (levels.Value.MaxLevel < level)
|
||||
lockStatus = LfgLockStatusType.TooHighLevel;
|
||||
}
|
||||
}
|
||||
|
||||
/* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
|
||||
lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE;
|
||||
lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL;
|
||||
lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
|
||||
*/
|
||||
if (lockStatus == 0)
|
||||
{
|
||||
|
||||
}
|
||||
if (lockStatus != 0)
|
||||
lockDic[dungeon.Entry()] = new LfgLockInfoData(lockStatus, dungeon.requiredItemLevel, player.GetAverageItemLevel());
|
||||
}
|
||||
@@ -1985,13 +1988,23 @@ namespace Game.DungeonFinding
|
||||
return 0;
|
||||
}
|
||||
|
||||
public List<uint> GetRandomAndSeasonalDungeons(uint level, uint expansion)
|
||||
public List<uint> GetRandomAndSeasonalDungeons(uint level, uint expansion, uint contentTuningReplacementConditionMask)
|
||||
{
|
||||
List<uint> randomDungeons = new List<uint>();
|
||||
foreach (var dungeon in LfgDungeonStore.Values)
|
||||
{
|
||||
if ((dungeon.seasonal && IsSeasonActive(dungeon.id) || !dungeon.seasonal && dungeon.type == LfgType.RandomDungeon) && dungeon.expansion <= expansion && dungeon.minlevel <= level && level <= dungeon.maxlevel)
|
||||
randomDungeons.Add(dungeon.Entry());
|
||||
if (!(dungeon.type == LfgType.RandomDungeon || (dungeon.seasonal && Global.LFGMgr.IsSeasonActive(dungeon.id))))
|
||||
continue;
|
||||
|
||||
if (dungeon.expansion > expansion)
|
||||
continue;
|
||||
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(dungeon.contentTuningId, contentTuningReplacementConditionMask);
|
||||
if (levels.HasValue)
|
||||
if (levels.Value.MinLevel > level || level > levels.Value.MaxLevel)
|
||||
continue;
|
||||
|
||||
randomDungeons.Add(dungeon.Entry());
|
||||
}
|
||||
return randomDungeons;
|
||||
}
|
||||
@@ -2184,8 +2197,7 @@ namespace Game.DungeonFinding
|
||||
type = dbc.TypeID;
|
||||
expansion = dbc.ExpansionLevel;
|
||||
group = dbc.GroupID;
|
||||
minlevel = dbc.MinLevel;
|
||||
maxlevel = dbc.MaxLevel;
|
||||
contentTuningId = dbc.ContentTuningID;
|
||||
difficulty = dbc.DifficultyID;
|
||||
seasonal = dbc.Flags[0].HasAnyFlag(LfgFlags.Seasonal);
|
||||
}
|
||||
@@ -2196,8 +2208,7 @@ namespace Game.DungeonFinding
|
||||
public LfgType type;
|
||||
public uint expansion;
|
||||
public uint group;
|
||||
public uint minlevel;
|
||||
public uint maxlevel;
|
||||
public uint contentTuningId;
|
||||
public Difficulty difficulty;
|
||||
public bool seasonal;
|
||||
public float x, y, z, o;
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
bool Create(uint spellMiscId, Unit caster, Unit target, SpellInfo spell, Position pos, int duration, SpellCastVisual spellVisual, ObjectGuid castId, AuraEffect aurEff)
|
||||
bool Create(uint spellMiscId, Unit caster, Unit target, SpellInfo spell, Position pos, int duration, SpellCastVisualField spellVisual, ObjectGuid castId, AuraEffect aurEff)
|
||||
{
|
||||
_targetGuid = target ? target.GetGUID() : ObjectGuid.Empty;
|
||||
_aurEff = aurEff;
|
||||
@@ -110,7 +110,11 @@ namespace Game.Entities
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellID), spell.Id);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellForVisuals), spell.Id);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellXSpellVisualID), spellVisual.SpellXSpellVisualID);
|
||||
|
||||
SpellCastVisualField spellCastVisual = m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.SpellVisual);
|
||||
SetUpdateFieldValue(ref spellCastVisual.SpellXSpellVisualID, spellVisual.SpellXSpellVisualID);
|
||||
SetUpdateFieldValue(ref spellCastVisual.ScriptVisualID, spellVisual.ScriptVisualID);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTargetScale), GetMiscTemplate().TimeToTargetScale != 0 ? GetMiscTemplate().TimeToTargetScale : m_areaTriggerData.Duration);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.BoundsRadius2D), GetTemplate().MaxSearchRadius);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.DecalPropertiesID), GetMiscTemplate().DecalPropertiesId);
|
||||
@@ -197,7 +201,7 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
public static AreaTrigger CreateAreaTrigger(uint spellMiscId, Unit caster, Unit target, SpellInfo spell, Position pos, int duration, SpellCastVisual spellVisual, ObjectGuid castId = default, AuraEffect aurEff = null)
|
||||
public static AreaTrigger CreateAreaTrigger(uint spellMiscId, Unit caster, Unit target, SpellInfo spell, Position pos, int duration, SpellCastVisualField spellVisual, ObjectGuid castId = default, AuraEffect aurEff = null)
|
||||
{
|
||||
AreaTrigger at = new AreaTrigger();
|
||||
if (!at.Create(spellMiscId, caster, target, spell, pos, duration, spellVisual, castId, aurEff))
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Game.Entities
|
||||
foreach (ushort actorIndex in actorIndices)
|
||||
{
|
||||
ConversationActor actor = actorIndex < m_conversationData.Actors.Size() ? m_conversationData.Actors[actorIndex] : null;
|
||||
if (actor == null || (actor.CreatureID == 0 && actor.ActorGUID.IsEmpty()))
|
||||
if (actor == null || (actor.CreatureID == 0 && actor.ActorGUID.IsEmpty() && actor.NoActorObject == 0))
|
||||
{
|
||||
Log.outError(LogFilter.Conversation, $"Failed to create conversation (Id: {conversationEntry}) due to missing actor (Idx: {actorIndex}).");
|
||||
return false;
|
||||
|
||||
@@ -101,10 +101,6 @@ namespace Game.Entities
|
||||
for (var i = 0; i < EquipmentSlot.End; ++i)
|
||||
items.Append($"{m_corpseData.Items[i]} ");
|
||||
|
||||
uint bytes1 = ((uint)m_corpseData.RaceID << 8) | ((uint)m_corpseData.Sex << 16) | ((uint)m_corpseData.SkinID << 24);
|
||||
uint bytes2 = ((uint)m_corpseData.FaceID) | ((uint)m_corpseData.HairStyleID << 8) | ((uint)m_corpseData.HairColorID << 16) | ((uint)m_corpseData.FacialHairStyleID << 24);
|
||||
|
||||
|
||||
byte index = 0;
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CORPSE);
|
||||
stmt.AddValue(index++, GetOwnerGUID().GetCounter()); // guid
|
||||
@@ -115,8 +111,8 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, GetMapId()); // mapId
|
||||
stmt.AddValue(index++, (uint)m_corpseData.DisplayID); // displayId
|
||||
stmt.AddValue(index++, items.ToString()); // itemCache
|
||||
stmt.AddValue(index++, bytes1); // bytes1
|
||||
stmt.AddValue(index++, bytes2); // bytes2
|
||||
stmt.AddValue(index++, m_corpseData.RaceID); // race
|
||||
stmt.AddValue(index++, m_corpseData.Sex); // gender
|
||||
stmt.AddValue(index++, (uint)m_corpseData.Flags); // flags
|
||||
stmt.AddValue(index++, (uint)m_corpseData.DynamicFlags); // dynFlags
|
||||
stmt.AddValue(index++, (uint)m_time); // time
|
||||
@@ -132,6 +128,18 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, phaseId); // PhaseId
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
foreach (var customization in m_corpseData.Customizations)
|
||||
{
|
||||
index = 0;
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CORPSE_CUSTOMIZATIONS);
|
||||
stmt.AddValue(index++, GetOwnerGUID().GetCounter()); // OwnerGuid
|
||||
stmt.AddValue(index++, customization.ChrCustomizationOptionID);
|
||||
stmt.AddValue(index++, customization.ChrCustomizationChoiceID);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
public void DeleteFromDB(SQLTransaction trans)
|
||||
@@ -148,12 +156,16 @@ namespace Game.Entities
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CORPSE_PHASES);
|
||||
stmt.AddValue(0, ownerGuid.GetCounter());
|
||||
DB.Characters.ExecuteOrAppend(trans, stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CORPSE_CUSTOMIZATIONS);
|
||||
stmt.AddValue(0, ownerGuid.GetCounter());
|
||||
DB.Characters.ExecuteOrAppend(trans, stmt);
|
||||
}
|
||||
|
||||
public bool LoadCorpseFromDB(ulong guid, SQLFields field)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?
|
||||
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, race, gender, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?
|
||||
|
||||
float posX = field.Read<float>(0);
|
||||
float posY = field.Read<float>(1);
|
||||
@@ -169,15 +181,8 @@ namespace Game.Entities
|
||||
for (uint index = 0; index < EquipmentSlot.End; ++index)
|
||||
SetItem(index, uint.Parse(items[(int)index]));
|
||||
|
||||
uint bytes1 = field.Read<uint>(7);
|
||||
uint bytes2 = field.Read<uint>(8);
|
||||
SetRace((Race)((bytes1 >> 8) & 0xFF));
|
||||
SetSex((Gender)((bytes1 >> 16) & 0xFF));
|
||||
SetSkin((byte)((bytes1 >> 24) & 0xFF));
|
||||
SetFace((byte)(bytes2 & 0xFF));
|
||||
SetHairStyle((byte)((bytes2 >> 8) & 0xFF));
|
||||
SetHairColor((byte)((bytes2 >> 16) & 0xFF));
|
||||
SetFacialHairStyle((byte)((bytes2 >> 24) & 0xFF));
|
||||
SetRace((Race)field.Read<byte>(7));
|
||||
SetSex((Gender)field.Read<byte>(8));
|
||||
SetFlags((CorpseFlags)field.Read<byte>(9));
|
||||
SetCorpseDynamicFlags((CorpseDynFlags)field.Read<byte>(10));
|
||||
SetOwnerGUID(ObjectGuid.Create(HighGuid.Player, field.Read<ulong>(14)));
|
||||
@@ -287,15 +292,21 @@ namespace Game.Entities
|
||||
public void SetDisplayId(uint displayId) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.DisplayID), displayId); }
|
||||
public void SetRace(Race race) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.RaceID), (byte)race); }
|
||||
public void SetSex(Gender sex) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Sex), (byte)sex); }
|
||||
public void SetSkin(byte skin) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.SkinID), skin); }
|
||||
public void SetFace(byte face) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.FaceID), face); }
|
||||
public void SetHairStyle(byte hairStyle) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.HairStyleID), hairStyle); }
|
||||
public void SetHairColor(byte hairColor) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.HairColorID), hairColor); }
|
||||
public void SetFacialHairStyle(byte facialHairStyle) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.FacialHairStyleID), facialHairStyle); }
|
||||
public void SetFlags(CorpseFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Flags), (uint)flags); }
|
||||
public void SetFactionTemplate(int factionTemplate) { SetUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.FactionTemplate), factionTemplate); }
|
||||
public void SetItem(uint slot, uint item) { SetUpdateFieldValue(ref m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Items, (int)slot), item); }
|
||||
public void SetCustomDisplayOption(uint slot, byte customDisplayOption) { SetUpdateFieldValue(ref m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.CustomDisplayOption, (int)slot), customDisplayOption); }
|
||||
|
||||
public void SetCustomizations(List<ChrCustomizationChoice> customizations)
|
||||
{
|
||||
ClearDynamicUpdateFieldValues(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Customizations));
|
||||
foreach (var customization in customizations)
|
||||
{
|
||||
var newChoice = new ChrCustomizationChoice();
|
||||
newChoice.ChrCustomizationOptionID = customization.ChrCustomizationOptionID;
|
||||
newChoice.ChrCustomizationChoiceID = customization.ChrCustomizationChoiceID;
|
||||
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_corpseData).ModifyValue(m_corpseData.Customizations), newChoice);
|
||||
}
|
||||
}
|
||||
|
||||
public long GetGhostTime() { return m_time; }
|
||||
public void ResetGhostTime() { m_time = Time.UnixTime; }
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public bool CreateDynamicObject(ulong guidlow, Unit caster, SpellInfo spell, Position pos, float radius, DynamicObjectType type, SpellCastVisual spellVisual)
|
||||
public bool CreateDynamicObject(ulong guidlow, Unit caster, SpellInfo spell, Position pos, float radius, DynamicObjectType type, SpellCastVisualField spellVisual)
|
||||
{
|
||||
SetMap(caster.GetMap());
|
||||
Relocate(pos);
|
||||
@@ -95,7 +95,11 @@ namespace Game.Entities
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.Caster), caster.GetGUID());
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.Type), (byte)type);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.SpellXSpellVisualID), spellVisual.SpellXSpellVisualID);
|
||||
|
||||
SpellCastVisualField spellCastVisual = m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.SpellVisual);
|
||||
SetUpdateFieldValue(ref spellCastVisual.SpellXSpellVisualID, spellVisual.SpellXSpellVisualID);
|
||||
SetUpdateFieldValue(ref spellCastVisual.ScriptVisualID, spellVisual.ScriptVisualID);
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.SpellID), spell.Id);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.Radius), radius);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_dynamicObjectData).ModifyValue(m_dynamicObjectData.CastTime), GameTime.GetGameTimeMS());
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Game.Entities
|
||||
for (int j = 0; j < SharedConst.MaxAzeriteEssenceSlot; ++j)
|
||||
stmt.AddValue(5 + specIndex * 5 + j, m_azeriteItemData.SelectedEssences[specIndex].AzeriteEssenceID[j]);
|
||||
}
|
||||
for (; specIndex < PlayerConst.MaxSpecializations; ++specIndex)
|
||||
for (; specIndex < 4; ++specIndex)
|
||||
{
|
||||
stmt.AddValue(4 + specIndex * 5, 0);
|
||||
for (int j = 0; j < SharedConst.MaxAzeriteEssenceSlot; ++j)
|
||||
@@ -557,6 +557,6 @@ namespace Game.Entities
|
||||
public uint KnowledgeLevel;
|
||||
public List<uint> AzeriteItemMilestonePowers = new List<uint>();
|
||||
public List<AzeriteEssencePowerRecord> UnlockedAzeriteEssences = new List<AzeriteEssencePowerRecord>();
|
||||
public AzeriteItemSelectedEssencesData[] SelectedAzeriteEssences = new AzeriteItemSelectedEssencesData[PlayerConst.MaxSpecializations];
|
||||
public AzeriteItemSelectedEssencesData[] SelectedAzeriteEssences = new AzeriteItemSelectedEssencesData[4];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1009,10 +1009,9 @@ namespace Game.Entities
|
||||
gemBonus.AddBonusList(bonusListId);
|
||||
|
||||
uint gemBaseItemLevel = gemTemplate.GetBaseItemLevel();
|
||||
ScalingStatDistributionRecord ssd = CliDB.ScalingStatDistributionStorage.LookupByKey(gemBonus.ScalingStatDistribution);
|
||||
if (ssd != null)
|
||||
if (gemBonus.PlayerLevelToItemLevelCurveId != 0)
|
||||
{
|
||||
uint scaledIlvl = (uint)Global.DB2Mgr.GetCurveValueAt(ssd.PlayerLevelToItemLevelCurveID, gemScalingLevel);
|
||||
uint scaledIlvl = (uint)Global.DB2Mgr.GetCurveValueAt(gemBonus.PlayerLevelToItemLevelCurveId, gemScalingLevel);
|
||||
if (scaledIlvl != 0)
|
||||
gemBaseItemLevel = scaledIlvl;
|
||||
}
|
||||
@@ -1446,7 +1445,7 @@ namespace Game.Entities
|
||||
Player owner = GetOwner();
|
||||
for (byte i = 0; i < ItemConst.MaxStats; ++i)
|
||||
{
|
||||
if ((owner ? GetItemStatValue(i, owner) : proto.GetItemStatAllocation(i)) != 0)
|
||||
if ((owner ? GetItemStatValue(i, owner) : proto.GetStatPercentEditor(i)) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1457,7 +1456,7 @@ namespace Game.Entities
|
||||
{
|
||||
for (byte i = 0; i < ItemConst.MaxStats; ++i)
|
||||
{
|
||||
if (bonus.ItemStatAllocation[i] != 0)
|
||||
if (bonus.StatPercentEditor[i] != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1767,22 +1766,18 @@ namespace Game.Entities
|
||||
if (azeriteLevelInfo != null)
|
||||
itemLevel = azeriteLevelInfo.ItemLevel;
|
||||
|
||||
ScalingStatDistributionRecord ssd = CliDB.ScalingStatDistributionStorage.LookupByKey(bonusData.ScalingStatDistribution);
|
||||
if (ssd != null)
|
||||
if (bonusData.PlayerLevelToItemLevelCurveId != 0)
|
||||
{
|
||||
if (fixedLevel != 0)
|
||||
level = fixedLevel;
|
||||
else
|
||||
level = (uint)Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
|
||||
{
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(bonusData.ContentTuningId, 0, true);
|
||||
if (levels.HasValue)
|
||||
level = (uint)Math.Min(Math.Max((ushort)level, levels.Value.MinLevel), levels.Value.MaxLevel);
|
||||
}
|
||||
|
||||
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(bonusData.ContentTuningId);
|
||||
if (contentTuning != null)
|
||||
if ((Convert.ToBoolean(contentTuning.Flags & 2) || contentTuning.MinLevel != 0 || contentTuning.MaxLevel != 0) && !Convert.ToBoolean(contentTuning.Flags & 4))
|
||||
level = (uint)Math.Min(Math.Max(level, contentTuning.MinLevel), contentTuning.MaxLevel);
|
||||
|
||||
uint heirloomIlvl = (uint)Global.DB2Mgr.GetCurveValueAt(ssd.PlayerLevelToItemLevelCurveID, level);
|
||||
if (heirloomIlvl != 0)
|
||||
itemLevel = heirloomIlvl;
|
||||
itemLevel = (uint)Global.DB2Mgr.GetCurveValueAt(bonusData.PlayerLevelToItemLevelCurveId, level);
|
||||
}
|
||||
|
||||
itemLevel += (uint)bonusData.ItemLevelBonus;
|
||||
@@ -1814,7 +1809,7 @@ namespace Game.Entities
|
||||
{
|
||||
case ItemModType.Corruption:
|
||||
case ItemModType.CorruptionResistance:
|
||||
return _bonusData.ItemStatAllocation[index];
|
||||
return _bonusData.StatPercentEditor[index];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1823,7 +1818,7 @@ namespace Game.Entities
|
||||
uint randomPropPoints = ItemEnchantmentManager.GetRandomPropertyPoints(itemLevel, GetQuality(), GetTemplate().GetInventoryType(), GetTemplate().GetSubClass());
|
||||
if (randomPropPoints != 0)
|
||||
{
|
||||
float statValue = (_bonusData.ItemStatAllocation[index] * randomPropPoints) * 0.0001f;
|
||||
float statValue = (_bonusData.StatPercentEditor[index] * randomPropPoints) * 0.0001f;
|
||||
GtItemSocketCostPerLevelRecord gtCost = CliDB.ItemSocketCostPerLevelGameTable.GetRow(itemLevel);
|
||||
if (gtCost != null)
|
||||
statValue -= (_bonusData.ItemStatSocketCostMultiplier[index] * gtCost.SocketCost);
|
||||
@@ -1881,11 +1876,11 @@ namespace Game.Entities
|
||||
|
||||
public uint GetDisplayId(Player owner)
|
||||
{
|
||||
ItemModifier transmogModifier = ItemModifier.TransmogAppearanceAllSpecs;
|
||||
if ((m_itemData.ModifiersMask & ItemConst.AppearanceModifierMaskSpecSpecific) != 0)
|
||||
transmogModifier = ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()];
|
||||
uint itemModifiedAppearanceId = GetModifier(ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]);
|
||||
if (itemModifiedAppearanceId == 0)
|
||||
itemModifiedAppearanceId = GetModifier(ItemModifier.TransmogAppearanceAllSpecs);
|
||||
|
||||
ItemModifiedAppearanceRecord transmog = CliDB.ItemModifiedAppearanceStorage.LookupByKey(GetModifier(transmogModifier));
|
||||
ItemModifiedAppearanceRecord transmog = CliDB.ItemModifiedAppearanceStorage.LookupByKey(itemModifiedAppearanceId);
|
||||
if (transmog != null)
|
||||
{
|
||||
ItemAppearanceRecord itemAppearance = CliDB.ItemAppearanceStorage.LookupByKey(transmog.ItemAppearanceID);
|
||||
@@ -1903,51 +1898,57 @@ namespace Game.Entities
|
||||
|
||||
public uint GetModifier(ItemModifier modifier)
|
||||
{
|
||||
if ((m_itemData.ModifiersMask & (1 << (int)modifier)) == 0)
|
||||
return 0;
|
||||
int modifierIndex = m_itemData.Modifiers._value.Values.FindIndexIf(mod =>
|
||||
{
|
||||
return mod.Type == (byte)modifier;
|
||||
});
|
||||
|
||||
int valueIndex = 0;
|
||||
uint mask = m_itemData.ModifiersMask;
|
||||
for (int i = 0; i < (int)modifier; ++i)
|
||||
if ((mask & (1 << i)) != 0)
|
||||
++valueIndex;
|
||||
if (modifierIndex != -1)
|
||||
return m_itemData.Modifiers._value.Values[modifierIndex].Value;
|
||||
|
||||
return m_itemData.Modifiers[valueIndex];
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetModifier(ItemModifier modifier, uint value)
|
||||
{
|
||||
int valueIndex = 0;
|
||||
uint mask = m_itemData.ModifiersMask;
|
||||
for (int i = 0; i < (int)modifier; ++i)
|
||||
if ((mask & (1 << i)) != 0)
|
||||
++valueIndex;
|
||||
int modifierIndex = m_itemData.Modifiers._value.Values.FindIndexIf(mod =>
|
||||
{
|
||||
return mod.Type == (byte)modifier;
|
||||
});
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
if ((mask & (1 << (int)modifier)) != 0)
|
||||
return;
|
||||
if (modifierIndex == -1)
|
||||
{
|
||||
ItemMod mod = new ItemMod();
|
||||
mod.Value = value;
|
||||
mod.Type = (byte)modifier;
|
||||
|
||||
SetUpdateFieldFlagValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ModifiersMask), 1u << (int)modifier);
|
||||
InsertDynamicUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.Modifiers), valueIndex, value);
|
||||
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.Modifiers)._value.ModifyValue(m_itemData.Modifiers._value.Values), mod);
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemModList itemModList = m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.Modifiers);
|
||||
itemModList.ModifyValue(itemModList.Values, modifierIndex);
|
||||
SetUpdateFieldValue(ref itemModList.ModifyValue(itemModList.Values, modifierIndex).GetValue().Value, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((mask & (1 << (int)modifier)) == 0)
|
||||
if (modifierIndex == -1)
|
||||
return;
|
||||
|
||||
RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ModifiersMask), 1u << (int)modifier);
|
||||
RemoveDynamicUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.Modifiers), valueIndex);
|
||||
RemoveDynamicUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.Modifiers)._value.ModifyValue(m_itemData.Modifiers._value.Values), modifierIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetVisibleEntry(Player owner)
|
||||
{
|
||||
ItemModifier transmogModifier = ItemModifier.TransmogAppearanceAllSpecs;
|
||||
if ((m_itemData.ModifiersMask & ItemConst.AppearanceModifierMaskSpecSpecific) != 0)
|
||||
transmogModifier = ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()];
|
||||
uint itemModifiedAppearanceId = GetModifier(ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]);
|
||||
if (itemModifiedAppearanceId == 0)
|
||||
itemModifiedAppearanceId = GetModifier(ItemModifier.TransmogAppearanceAllSpecs);
|
||||
|
||||
ItemModifiedAppearanceRecord transmog = CliDB.ItemModifiedAppearanceStorage.LookupByKey(GetModifier(transmogModifier));
|
||||
ItemModifiedAppearanceRecord transmog = CliDB.ItemModifiedAppearanceStorage.LookupByKey(itemModifiedAppearanceId);
|
||||
if (transmog != null)
|
||||
return transmog.ItemID;
|
||||
|
||||
@@ -1956,11 +1957,11 @@ namespace Game.Entities
|
||||
|
||||
public ushort GetVisibleAppearanceModId(Player owner)
|
||||
{
|
||||
ItemModifier transmogModifier = ItemModifier.TransmogAppearanceAllSpecs;
|
||||
if ((m_itemData.ModifiersMask & ItemConst.AppearanceModifierMaskSpecSpecific) != 0)
|
||||
transmogModifier = ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()];
|
||||
uint itemModifiedAppearanceId = GetModifier(ItemConst.AppearanceModifierSlotBySpec[owner.GetActiveTalentGroup()]);
|
||||
if (itemModifiedAppearanceId == 0)
|
||||
itemModifiedAppearanceId = GetModifier(ItemModifier.TransmogAppearanceAllSpecs);
|
||||
|
||||
ItemModifiedAppearanceRecord transmog = CliDB.ItemModifiedAppearanceStorage.LookupByKey(GetModifier(transmogModifier));
|
||||
ItemModifiedAppearanceRecord transmog = CliDB.ItemModifiedAppearanceStorage.LookupByKey(itemModifiedAppearanceId);
|
||||
if (transmog != null)
|
||||
return transmog.ItemAppearanceModifierID;
|
||||
|
||||
@@ -1969,15 +1970,14 @@ namespace Game.Entities
|
||||
|
||||
public uint GetVisibleEnchantmentId(Player owner)
|
||||
{
|
||||
ItemModifier illusionModifier = ItemModifier.EnchantIllusionAllSpecs;
|
||||
if ((m_itemData.ModifiersMask & ItemConst.IllusionModifierMaskSpecSpecific) != 0)
|
||||
illusionModifier = ItemConst.IllusionModifierSlotBySpec[owner.GetActiveTalentGroup()];
|
||||
uint enchantmentId = GetModifier(ItemConst.IllusionModifierSlotBySpec[owner.GetActiveTalentGroup()]);
|
||||
if (enchantmentId == 0)
|
||||
enchantmentId = GetModifier(ItemModifier.EnchantIllusionAllSpecs);
|
||||
|
||||
uint enchantIllusion = GetModifier(illusionModifier);
|
||||
if (enchantIllusion != 0)
|
||||
return enchantIllusion;
|
||||
if (enchantmentId == 0)
|
||||
enchantmentId = GetEnchantmentId(EnchantmentSlot.Perm);
|
||||
|
||||
return (uint)GetEnchantmentId(EnchantmentSlot.Perm);
|
||||
return enchantmentId;
|
||||
}
|
||||
|
||||
public ushort GetVisibleItemVisual(Player owner)
|
||||
@@ -2255,15 +2255,11 @@ namespace Game.Entities
|
||||
if (!_bonusData.HasFixedLevel || GetModifier(ItemModifier.TimewalkerLevel) != 0)
|
||||
return;
|
||||
|
||||
ScalingStatDistributionRecord ssd = CliDB.ScalingStatDistributionStorage.LookupByKey(_bonusData.ScalingStatDistribution);
|
||||
if (ssd != null)
|
||||
if (_bonusData.PlayerLevelToItemLevelCurveId != 0)
|
||||
{
|
||||
level = (uint)Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
|
||||
|
||||
ContentTuningRecord contentTuning = CliDB.ContentTuningStorage.LookupByKey(_bonusData.ContentTuningId);
|
||||
if (contentTuning != null)
|
||||
if ((contentTuning.Flags.HasAnyFlag(2) || contentTuning.MinLevel != 0 || contentTuning.MaxLevel != 0) && !contentTuning.Flags.HasAnyFlag(4))
|
||||
level = (uint)Math.Min(Math.Max(level, contentTuning.MinLevel), contentTuning.MaxLevel);
|
||||
var levels = Global.DB2Mgr.GetContentTuningData(_bonusData.ContentTuningId, 0, true);
|
||||
if (levels.HasValue)
|
||||
level = (uint)Math.Min(Math.Max((short)level, levels.Value.MinLevel), levels.Value.MaxLevel);
|
||||
|
||||
SetModifier(ItemModifier.TimewalkerLevel, level);
|
||||
}
|
||||
@@ -2271,12 +2267,14 @@ namespace Game.Entities
|
||||
|
||||
public int GetRequiredLevel()
|
||||
{
|
||||
int fixedLevel = (int)GetModifier(ItemModifier.TimewalkerLevel);
|
||||
if (_bonusData.RequiredLevelCurve != 0)
|
||||
return (int)Global.DB2Mgr.GetCurveValueAt(_bonusData.RequiredLevelCurve, fixedLevel);
|
||||
if (_bonusData.RequiredLevelOverride != 0)
|
||||
return _bonusData.RequiredLevelOverride;
|
||||
else if (_bonusData.HasFixedLevel)
|
||||
return (int)GetModifier(ItemModifier.TimewalkerLevel);
|
||||
else
|
||||
return _bonusData.RequiredLevel;
|
||||
if (_bonusData.HasFixedLevel && _bonusData.PlayerLevelToItemLevelCurveId != 0)
|
||||
return fixedLevel;
|
||||
return _bonusData.RequiredLevel;
|
||||
}
|
||||
|
||||
public static Item NewItemOrBag(ItemTemplate proto)
|
||||
@@ -2515,7 +2513,7 @@ namespace Game.Entities
|
||||
public uint GetAppearanceModId() { return m_itemData.ItemAppearanceModID; }
|
||||
public void SetAppearanceModId(uint appearanceModId) { SetUpdateFieldValue(m_values.ModifyValue(m_itemData).ModifyValue(m_itemData.ItemAppearanceModID), (byte)appearanceModId); }
|
||||
public float GetRepairCostMultiplier() { return _bonusData.RepairCostMultiplier; }
|
||||
public uint GetScalingStatDistribution() { return _bonusData.ScalingStatDistribution; }
|
||||
public uint GetScalingContentTuningId() { return _bonusData.ContentTuningId; }
|
||||
|
||||
public void SetRefundRecipient(ObjectGuid guid) { m_refundRecipient = guid; }
|
||||
public void SetPaidMoney(ulong money) { m_paidMoney = money; }
|
||||
@@ -2685,13 +2683,13 @@ namespace Game.Entities
|
||||
ItemLevelBonus = 0;
|
||||
RequiredLevel = proto.GetBaseRequiredLevel();
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
ItemStatType[i] = proto.GetItemStatType(i);
|
||||
ItemStatType[i] = proto.GetStatModifierBonusStat(i);
|
||||
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
ItemStatAllocation[i] = proto.GetItemStatAllocation(i);
|
||||
StatPercentEditor[i] = proto.GetStatPercentEditor(i);
|
||||
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
ItemStatSocketCostMultiplier[i] = proto.GetItemStatSocketCostMultiplier(i);
|
||||
ItemStatSocketCostMultiplier[i] = proto.GetStatPercentageOfSocket(i);
|
||||
|
||||
for (uint i = 0; i < ItemConst.MaxGemSockets; ++i)
|
||||
{
|
||||
@@ -2705,7 +2703,8 @@ namespace Game.Entities
|
||||
|
||||
AppearanceModID = 0;
|
||||
RepairCostMultiplier = 1.0f;
|
||||
ScalingStatDistribution = proto.GetScalingStatDistribution();
|
||||
ContentTuningId = proto.GetScalingStatContentTuning();
|
||||
PlayerLevelToItemLevelCurveId = proto.GetPlayerLevelToItemLevelCurveId();
|
||||
RelicType = -1;
|
||||
HasFixedLevel = false;
|
||||
RequiredLevelOverride = 0;
|
||||
@@ -2729,6 +2728,7 @@ namespace Game.Entities
|
||||
_state.AppearanceModPriority = int.MaxValue;
|
||||
_state.ScalingStatDistributionPriority = int.MaxValue;
|
||||
_state.AzeriteTierUnlockSetPriority = int.MaxValue;
|
||||
_state.RequiredLevelCurvePriority = int.MaxValue;
|
||||
_state.HasQualityBonus = false;
|
||||
}
|
||||
|
||||
@@ -2766,7 +2766,7 @@ namespace Game.Entities
|
||||
if (statIndex < ItemConst.MaxStats)
|
||||
{
|
||||
ItemStatType[statIndex] = values[0];
|
||||
ItemStatAllocation[statIndex] += values[1];
|
||||
StatPercentEditor[statIndex] += values[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2816,8 +2816,8 @@ namespace Game.Entities
|
||||
case ItemBonusType.ScalingStatDistributionFixed:
|
||||
if (values[1] < _state.ScalingStatDistributionPriority)
|
||||
{
|
||||
ScalingStatDistribution = (uint)values[0];
|
||||
ContentTuningId = (uint)values[2];
|
||||
PlayerLevelToItemLevelCurveId = (uint)values[3];
|
||||
_state.ScalingStatDistributionPriority = values[1];
|
||||
HasFixedLevel = type == ItemBonusType.ScalingStatDistributionFixed;
|
||||
}
|
||||
@@ -2849,6 +2849,15 @@ namespace Game.Entities
|
||||
if (itemEffect != null)
|
||||
Effects[EffectCount++] = itemEffect;
|
||||
break;
|
||||
case ItemBonusType.RequiredLevelCurve:
|
||||
if (values[2] < _state.RequiredLevelCurvePriority)
|
||||
{
|
||||
RequiredLevelCurve = (uint)values[0];
|
||||
_state.RequiredLevelCurvePriority = values[2];
|
||||
if (values[1] != 0)
|
||||
ContentTuningId = (uint)values[1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2856,14 +2865,14 @@ namespace Game.Entities
|
||||
public int ItemLevelBonus;
|
||||
public int RequiredLevel;
|
||||
public int[] ItemStatType = new int[ItemConst.MaxStats];
|
||||
public int[] ItemStatAllocation = new int[ItemConst.MaxStats];
|
||||
public int[] StatPercentEditor = new int[ItemConst.MaxStats];
|
||||
public float[] ItemStatSocketCostMultiplier = new float[ItemConst.MaxStats];
|
||||
public SocketColor[] socketColor = new SocketColor[ItemConst.MaxGemSockets];
|
||||
public ItemBondingType Bonding;
|
||||
public uint AppearanceModID;
|
||||
public float RepairCostMultiplier;
|
||||
public uint ScalingStatDistribution;
|
||||
public uint ContentTuningId;
|
||||
public uint PlayerLevelToItemLevelCurveId;
|
||||
public uint DisenchantLootId;
|
||||
public uint[] GemItemLevelBonus = new uint[ItemConst.MaxGemSockets];
|
||||
public int[] GemRelicType = new int[ItemConst.MaxGemSockets];
|
||||
@@ -2872,6 +2881,7 @@ namespace Game.Entities
|
||||
public int RequiredLevelOverride;
|
||||
public uint AzeriteTierUnlockSetId;
|
||||
public uint Suffix;
|
||||
public uint RequiredLevelCurve;
|
||||
public ItemEffectRecord[] Effects = new ItemEffectRecord[13];
|
||||
public int EffectCount;
|
||||
public bool CanDisenchant;
|
||||
@@ -2885,6 +2895,7 @@ namespace Game.Entities
|
||||
public int AppearanceModPriority;
|
||||
public int ScalingStatDistributionPriority;
|
||||
public int AzeriteTierUnlockSetPriority;
|
||||
public int RequiredLevelCurvePriority;
|
||||
public bool HasQualityBonus;
|
||||
}
|
||||
}
|
||||
@@ -2972,7 +2983,7 @@ namespace Game.Entities
|
||||
info.AzeriteItem.Xp = azeriteItemResult.Read<ulong>(1);
|
||||
info.AzeriteItem.Level = azeriteItemResult.Read<uint>(2);
|
||||
info.AzeriteItem.KnowledgeLevel = azeriteItemResult.Read<uint>(3);
|
||||
for (int i = 0; i < PlayerConst.MaxSpecializations; ++i)
|
||||
for (int i = 0; i < info.AzeriteItem.SelectedAzeriteEssences.Length; ++i)
|
||||
{
|
||||
uint specializationId = azeriteItemResult.Read<uint>(4 + i * 4);
|
||||
if (!CliDB.ChrSpecializationStorage.ContainsKey(specializationId))
|
||||
|
||||
@@ -277,22 +277,11 @@ namespace Game.Entities
|
||||
public uint GetRequiredReputationRank() { return ExtendedData.MinReputation; }
|
||||
public uint GetMaxCount() { return ExtendedData.MaxCount; }
|
||||
public uint GetContainerSlots() { return ExtendedData.ContainerSlots; }
|
||||
public int GetItemStatType(uint index)
|
||||
{
|
||||
Cypher.Assert(index < ItemConst.MaxStats);
|
||||
return ExtendedData.StatModifierBonusStat[index];
|
||||
}
|
||||
public int GetItemStatAllocation(uint index)
|
||||
{
|
||||
Cypher.Assert(index < ItemConst.MaxStats);
|
||||
return ExtendedData.StatPercentEditor[index];
|
||||
}
|
||||
public float GetItemStatSocketCostMultiplier(uint index)
|
||||
{
|
||||
Cypher.Assert(index < ItemConst.MaxStats);
|
||||
return ExtendedData.StatPercentageOfSocket[index];
|
||||
}
|
||||
public uint GetScalingStatDistribution() { return ExtendedData.ScalingStatDistributionID; }
|
||||
public int GetStatModifierBonusStat(uint index) { Cypher.Assert(index < ItemConst.MaxStats); return ExtendedData.StatModifierBonusStat[index]; }
|
||||
public int GetStatPercentEditor(uint index) { Cypher.Assert(index < ItemConst.MaxStats); return ExtendedData.StatPercentEditor[index]; }
|
||||
public float GetStatPercentageOfSocket(uint index) { Cypher.Assert(index < ItemConst.MaxStats); return ExtendedData.StatPercentageOfSocket[index]; }
|
||||
public uint GetScalingStatContentTuning() { return ExtendedData.ContentTuningID; }
|
||||
public uint GetPlayerLevelToItemLevelCurveId() { return ExtendedData.PlayerLevelToItemLevelCurveID; }
|
||||
public uint GetDamageType() { return ExtendedData.DamageType; }
|
||||
public uint GetDelay() { return ExtendedData.ItemDelay; }
|
||||
public float GetRangedModRange() { return ExtendedData.ItemRange; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1832,6 +1832,38 @@ namespace Game.Entities
|
||||
pair.Value.state = PlayerCurrencyState.Unchanged;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SavePlayerCustomizations(SQLTransaction trans, ulong guid, List<ChrCustomizationChoice> customizations)
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_CUSTOMIZATIONS);
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
foreach (var customization in customizations)
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_CUSTOMIZATION);
|
||||
stmt.AddValue(0, guid);
|
||||
stmt.AddValue(1, customization.ChrCustomizationOptionID);
|
||||
stmt.AddValue(2, customization.ChrCustomizationChoiceID);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveCustomizations(SQLTransaction trans, ulong guid, List<ChrCustomizationChoice> customizations)
|
||||
{
|
||||
SavePlayerCustomizations(trans, guid, customizations);
|
||||
}
|
||||
|
||||
void _SaveCustomizations(SQLTransaction trans)
|
||||
{
|
||||
if (!m_customizationsChanged)
|
||||
return;
|
||||
|
||||
m_customizationsChanged = false;
|
||||
|
||||
SavePlayerCustomizations(trans, GetGUID().GetCounter(), m_playerData.Customizations);
|
||||
}
|
||||
|
||||
void _SaveActions(SQLTransaction trans)
|
||||
{
|
||||
PreparedStatement stmt = null;
|
||||
@@ -2418,19 +2450,86 @@ namespace Game.Entities
|
||||
SQLResult result = holder.GetResult(PlayerLoginQueryLoad.From);
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
string name;
|
||||
Global.CharacterCacheStorage.GetCharacterNameByGuid(guid, out name);
|
||||
Log.outError(LogFilter.Player, "Player {0} {1} not found in table `characters`, can't load. ", name, guid.ToString());
|
||||
Global.CharacterCacheStorage.GetCharacterNameByGuid(guid, out string cacheName);
|
||||
Log.outError(LogFilter.Player, "Player {0} {1} not found in table `characters`, can't load. ", cacheName, guid.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
uint dbAccountId = result.Read<uint>(1);
|
||||
int fieldIndex = 1;
|
||||
uint accountId = result.Read<uint>(fieldIndex++);
|
||||
string name = result.Read<string>(fieldIndex++);
|
||||
Race race = (Race)result.Read<byte>(fieldIndex++);
|
||||
Class class_ = (Class)result.Read<byte>(fieldIndex++);
|
||||
Gender gender = (Gender)result.Read<byte>(fieldIndex++);
|
||||
byte level = result.Read<byte>(fieldIndex++);
|
||||
uint xp = result.Read<uint>(fieldIndex++);
|
||||
ulong money = result.Read<ulong>(fieldIndex++);
|
||||
byte inventorySlots = result.Read<byte>(fieldIndex++);
|
||||
byte bankSlots = result.Read<byte>(fieldIndex++);
|
||||
PlayerRestState restState = (PlayerRestState)result.Read<byte>(fieldIndex++);
|
||||
PlayerFlags playerFlags = (PlayerFlags)result.Read<uint>(fieldIndex++);
|
||||
PlayerFlagsEx playerFlagsEx = (PlayerFlagsEx)result.Read<uint>(fieldIndex++);
|
||||
float position_x = result.Read<float>(fieldIndex++);
|
||||
float position_y = result.Read<float>(fieldIndex++);
|
||||
float position_z = result.Read<float>(fieldIndex++);
|
||||
uint mapId = result.Read<ushort>(fieldIndex++);
|
||||
float orientation = result.Read<float>(fieldIndex++);
|
||||
string taximask = result.Read<string>(fieldIndex++);
|
||||
byte cinematic = result.Read<byte>(fieldIndex++);
|
||||
uint totaltime = result.Read<uint> (fieldIndex++);
|
||||
uint leveltime = result.Read<uint>(fieldIndex++);
|
||||
float rest_bonus = result.Read<float>(fieldIndex++);
|
||||
uint logout_time = result.Read<uint>(fieldIndex++);
|
||||
byte is_logout_resting = result.Read<byte>(fieldIndex++);
|
||||
uint resettalents_cost = result.Read<uint>(fieldIndex++);
|
||||
uint resettalents_time = result.Read<uint>(fieldIndex++);
|
||||
uint primarySpecialization = result.Read<uint>(fieldIndex++);
|
||||
float trans_x = result.Read<float>(fieldIndex++);
|
||||
float trans_y = result.Read<float>(fieldIndex++);
|
||||
float trans_z = result.Read<float>(fieldIndex++);
|
||||
float trans_o = result.Read<float>(fieldIndex++);
|
||||
ulong transguid = result.Read<ulong>(fieldIndex++);
|
||||
PlayerExtraFlags extra_flags = (PlayerExtraFlags)result.Read<ushort>(fieldIndex++);
|
||||
byte stable_slots = result.Read<byte>(fieldIndex++);
|
||||
ushort at_login = result.Read<ushort>(fieldIndex++);
|
||||
ushort zone = result.Read<ushort>(fieldIndex++);
|
||||
byte online = result.Read<byte>(fieldIndex++);
|
||||
uint death_expire_time = result.Read<uint>(fieldIndex++);
|
||||
string taxi_path = result.Read<string>(fieldIndex++);
|
||||
Difficulty dungeonDifficulty = (Difficulty)result.Read<byte>(fieldIndex++);
|
||||
uint totalKills = result.Read<uint>(fieldIndex++);
|
||||
ushort todayKills = result.Read<ushort>(fieldIndex++);
|
||||
ushort yesterdayKills = result.Read<ushort>(fieldIndex++);
|
||||
uint chosenTitle = result.Read<uint>(fieldIndex++);
|
||||
uint watchedFaction = result.Read<uint>(fieldIndex++);
|
||||
byte drunk = result.Read<byte>(fieldIndex++);
|
||||
uint health = result.Read<uint>(fieldIndex++);
|
||||
|
||||
uint[] powers = new uint[(int)PowerType.MaxPerClass];
|
||||
for (var i = 0; fieldIndex < powers.Length; ++i)
|
||||
powers[i] = result.Read<uint>(fieldIndex++);
|
||||
|
||||
uint instance_id = result.Read<uint>(fieldIndex++);
|
||||
byte activeTalentGroup = result.Read<byte>(fieldIndex++);
|
||||
uint lootSpecId = result.Read<uint>(fieldIndex++);
|
||||
string exploredZones = result.Read<string>(fieldIndex++);
|
||||
string knownTitles = result.Read<string>(fieldIndex++);
|
||||
byte actionBars = result.Read<byte>(fieldIndex++);
|
||||
Difficulty raidDifficulty = (Difficulty)result.Read<byte>(fieldIndex++);
|
||||
Difficulty legacyRaidDifficulty = (Difficulty)result.Read<byte>(fieldIndex++);
|
||||
byte fishingSteps = result.Read<byte>(fieldIndex++);
|
||||
uint honor = result.Read<uint>(fieldIndex++);
|
||||
uint honorLevel = result.Read<uint>(fieldIndex++);
|
||||
PlayerRestState honorRestState = (PlayerRestState)result.Read<byte>(fieldIndex++);
|
||||
float honorRestBonus = result.Read<float>(fieldIndex++);
|
||||
byte numRespecs = result.Read<byte>(fieldIndex++);
|
||||
|
||||
|
||||
// check if the character's account in the db and the logged in account match.
|
||||
// player should be able to load/delete character only with correct account!
|
||||
if (dbAccountId != GetSession().GetAccountId())
|
||||
if (accountId != GetSession().GetAccountId())
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player (GUID: {0}) loading from wrong account (is: {1}, should be: {2})", GetGUID().ToString(), GetSession().GetAccountId(), dbAccountId);
|
||||
Log.outError(LogFilter.Player, "Player (GUID: {0}) loading from wrong account (is: {1}, should be: {2})", GetGUID().ToString(), GetSession().GetAccountId(), accountId);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2443,7 +2542,7 @@ namespace Game.Entities
|
||||
|
||||
_Create(guid);
|
||||
|
||||
SetName(result.Read<string>(2));
|
||||
SetName(name);
|
||||
|
||||
// check name limitations
|
||||
if (ObjectManager.CheckPlayerName(GetName(), GetSession().GetSessionDbcLocale()) != ResponseCodes.CharNameSuccess ||
|
||||
@@ -2456,18 +2555,18 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
// overwrite possible wrong/corrupted guid
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.WowAccount), GetSession().GetAccountGUID());
|
||||
|
||||
Gender gender = (Gender)result.Read<byte>(5);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.WowAccount), GetSession().GetAccountGUID());
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.BnetAccount), GetSession().GetBattlenetAccountGUID());
|
||||
|
||||
if (gender >= Gender.None)
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player {0} has wrong gender ({1}), can't be loaded.", guid.ToString(), gender);
|
||||
return false;
|
||||
}
|
||||
|
||||
SetRace((Race)result.Read<byte>(3));
|
||||
SetClass((Class)result.Read<byte>(4));
|
||||
SetRace(race);
|
||||
SetClass(class_);
|
||||
SetGender(gender);
|
||||
|
||||
// check if race/class combination is valid
|
||||
@@ -2478,19 +2577,19 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
SetLevel(result.Read<uint>(6));
|
||||
SetXP(result.Read<uint>(7));
|
||||
SetLevel(level);
|
||||
SetXP(xp);
|
||||
|
||||
StringArray exploredZones = new StringArray(result.Read<string>(66), ' ');
|
||||
if (exploredZones.Length == PlayerConst.ExploredZonesSize * 2)
|
||||
for (int i = 0; i < exploredZones.Length; ++i)
|
||||
SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ExploredZones, i / 2), (ulong)((long.Parse(exploredZones[i])) << (32 * (i % 2))));
|
||||
StringArray exploredZonesStrings = new StringArray(exploredZones, ' ');
|
||||
if (exploredZonesStrings.Length == PlayerConst.ExploredZonesSize * 2)
|
||||
for (int i = 0; i < exploredZonesStrings.Length; ++i)
|
||||
SetUpdateFieldFlagValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ExploredZones, i / 2), (ulong)((long.Parse(exploredZonesStrings[i])) << (32 * (i % 2))));
|
||||
|
||||
StringArray knownTitles = new StringArray(result.Read<string>(67), ' ');
|
||||
if ((knownTitles.Length % 2) == 0)
|
||||
StringArray knownTitlesStrings = new StringArray(knownTitles, ' ');
|
||||
if ((knownTitlesStrings.Length % 2) == 0)
|
||||
{
|
||||
for (int i = 0; i < knownTitles.Length; ++i)
|
||||
SetUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.KnownTitles, i / 2), (ulong)((long.Parse(knownTitles[i])) << (32 * (i % 2))));
|
||||
for (int i = 0; i < knownTitlesStrings.Length; ++i)
|
||||
SetUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.KnownTitles, i / 2), (ulong)((long.Parse(knownTitlesStrings[i])) << (32 * (i % 2))));
|
||||
}
|
||||
|
||||
SetObjectScale(1.0f);
|
||||
@@ -2500,42 +2599,42 @@ namespace Game.Entities
|
||||
m_achievementSys.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.Achievements), holder.GetResult(PlayerLoginQueryLoad.CriteriaProgress));
|
||||
m_questObjectiveCriteriaMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.QuestStatusObjectivesCriteria), holder.GetResult(PlayerLoginQueryLoad.QuestStatusObjectivesCriteriaProgress));
|
||||
|
||||
ulong money = result.Read<ulong>(8);
|
||||
if (money > PlayerConst.MaxMoneyAmount)
|
||||
money = PlayerConst.MaxMoneyAmount;
|
||||
SetMoney(money);
|
||||
SetMoney(Math.Min(money, PlayerConst.MaxMoneyAmount));
|
||||
|
||||
Array<byte> customDisplay = new Array<byte>(PlayerConst.CustomDisplaySize);
|
||||
customDisplay[0] = result.Read<byte>(14);
|
||||
customDisplay[1] = result.Read<byte>(15);
|
||||
customDisplay[2] = result.Read<byte>(16);
|
||||
List<ChrCustomizationChoice> customizations = new List<ChrCustomizationChoice>();
|
||||
SQLResult customizationsResult = holder.GetResult(PlayerLoginQueryLoad.Customizations);
|
||||
if (!customizationsResult.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
|
||||
SetSkinId(result.Read<byte>(9));
|
||||
SetFaceId(result.Read<byte>(10));
|
||||
SetHairStyleId(result.Read<byte>(11));
|
||||
SetHairColorId(result.Read<byte>(12));
|
||||
SetFacialHairStyleId(result.Read<byte>(13));
|
||||
for (byte i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
SetCustomDisplayOption(i, customDisplay[i]);
|
||||
SetInventorySlotCount(result.Read<byte>(17));
|
||||
SetBankBagSlotCount(result.Read<byte>(18));
|
||||
ChrCustomizationChoice choice;
|
||||
choice.ChrCustomizationOptionID = customizationsResult.Read<uint>(0);
|
||||
choice.ChrCustomizationChoiceID = customizationsResult.Read<uint>(1);
|
||||
customizations.Add(choice);
|
||||
|
||||
} while (customizationsResult.NextRow());
|
||||
}
|
||||
|
||||
SetCustomizations(customizations, false);
|
||||
SetInventorySlotCount(inventorySlots);
|
||||
SetBankBagSlotCount(bankSlots);
|
||||
SetNativeSex(gender);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.Inebriation), result.Read<byte>(55));
|
||||
SetPlayerFlags((PlayerFlags)result.Read<uint>(20));
|
||||
SetPlayerFlagsEx((PlayerFlagsEx)result.Read<uint>(21));
|
||||
SetWatchedFactionIndex(result.Read<uint>(54));
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.Inebriation), drunk);
|
||||
SetPlayerFlags(playerFlags);
|
||||
SetPlayerFlagsEx(playerFlagsEx);
|
||||
SetWatchedFactionIndex(watchedFaction);
|
||||
|
||||
if (!ValidateAppearance((Race)result.Read<byte>(3), (Class)result.Read<byte>(4), (Gender)gender,
|
||||
m_playerData.HairStyleID, m_playerData.HairColorID, m_playerData.FaceID, m_playerData.FacialHairStyleID, m_playerData.SkinID, customDisplay))
|
||||
if (!GetSession().ValidateAppearance(GetRace(), GetClass(), gender, customizations))
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player {0} has wrong Appearance values (Hair/Skin/Color), can't be loaded.", guid.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
|
||||
SetMultiActionBars(result.Read<byte>(68));
|
||||
SetMultiActionBars(actionBars);
|
||||
|
||||
m_fishingSteps = result.Read<byte>(71);
|
||||
m_fishingSteps = fishingSteps;
|
||||
|
||||
InitDisplayIds();
|
||||
|
||||
@@ -2560,27 +2659,20 @@ namespace Game.Entities
|
||||
InitPrimaryProfessions(); // to max set before any spell loaded
|
||||
|
||||
// init saved position, and fix it later if problematic
|
||||
ulong transLowGUID = result.Read<ulong>(41);
|
||||
Relocate(position_x, position_y, position_z, orientation);
|
||||
|
||||
Relocate(result.Read<float>(22), result.Read<float>(23), result.Read<float>(24), result.Read<float>(26));
|
||||
SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID(dungeonDifficulty));
|
||||
SetRaidDifficultyID(CheckLoadedRaidDifficultyID(raidDifficulty));
|
||||
SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID(legacyRaidDifficulty));
|
||||
|
||||
uint mapId = result.Read<uint>(25);
|
||||
uint instanceId = result.Read<uint>(63);
|
||||
|
||||
var RelocateToHomebind = new Action(() => { mapId = homebind.GetMapId(); instanceId = 0; Relocate(homebind); });
|
||||
|
||||
SetDungeonDifficultyID(CheckLoadedDungeonDifficultyID((Difficulty)result.Read<byte>(49)));
|
||||
SetRaidDifficultyID(CheckLoadedRaidDifficultyID((Difficulty)result.Read<byte>(69)));
|
||||
SetLegacyRaidDifficultyID(CheckLoadedLegacyRaidDifficultyID((Difficulty)result.Read<byte>(70)));
|
||||
|
||||
string taxi_nodes = result.Read<string>(48);
|
||||
var RelocateToHomebind = new Action(() => { mapId = (ushort)homebind.GetMapId(); instance_id = 0; Relocate(homebind); });
|
||||
|
||||
_LoadGroup(holder.GetResult(PlayerLoginQueryLoad.Group));
|
||||
|
||||
_LoadCurrency(holder.GetResult(PlayerLoginQueryLoad.Currency));
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LifetimeHonorableKills), result.Read<uint>(50));
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TodayHonorableKills), result.Read<ushort>(51));
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.YesterdayHonorableKills), result.Read<ushort>(52));
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LifetimeHonorableKills), totalKills);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TodayHonorableKills), todayKills);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.YesterdayHonorableKills), yesterdayKills);
|
||||
|
||||
_LoadBoundInstances(holder.GetResult(PlayerLoginQueryLoad.BoundInstances));
|
||||
_LoadInstanceTimeRestrictions(holder.GetResult(PlayerLoginQueryLoad.InstanceLockTimes));
|
||||
@@ -2632,7 +2724,7 @@ namespace Game.Entities
|
||||
// Do not look for instance if bg not found
|
||||
WorldLocation _loc = GetBattlegroundEntryPoint();
|
||||
mapId = _loc.GetMapId();
|
||||
instanceId = 0;
|
||||
instance_id = 0;
|
||||
|
||||
if (mapId == 0xFFFFFFFF) // BattlegroundEntry Point not found (???)
|
||||
{
|
||||
@@ -2647,9 +2739,9 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
// currently we do not support transport in bg
|
||||
else if (transLowGUID != 0)
|
||||
else if (transguid != 0)
|
||||
{
|
||||
ObjectGuid transGUID = ObjectGuid.Create(HighGuid.Transport, transLowGUID);
|
||||
ObjectGuid transGUID = ObjectGuid.Create(HighGuid.Transport, transguid);
|
||||
|
||||
Transport transport = null;
|
||||
Transport go = Global.ObjAccessor.FindTransport(transGUID);
|
||||
@@ -2658,10 +2750,11 @@ namespace Game.Entities
|
||||
|
||||
if (transport)
|
||||
{
|
||||
float x = result.Read<float>(37);
|
||||
float y = result.Read<float>(38);
|
||||
float z = result.Read<float>(39);
|
||||
float o = result.Read<float>(40);
|
||||
float x = trans_x;
|
||||
float y = trans_y;
|
||||
float z = trans_z;
|
||||
float o = trans_o;
|
||||
|
||||
m_movementInfo.transport.pos = new Position(x, y, z, o);
|
||||
transport.CalculatePassengerPosition(ref x, ref y, ref z, ref o);
|
||||
|
||||
@@ -2671,8 +2764,7 @@ namespace Game.Entities
|
||||
Math.Abs(m_movementInfo.transport.pos.posY) > 250.0f ||
|
||||
Math.Abs(m_movementInfo.transport.pos.posZ) > 250.0f)
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player (guidlow {0}) have invalid transport coordinates (X: {1} Y: {2} Z: {3} O: {4}). Teleport to bind location.",
|
||||
guid.ToString(), x, y, z, o);
|
||||
Log.outError(LogFilter.Player, "Player (guidlow {0}) have invalid transport coordinates (X: {1} Y: {2} Z: {3} O: {4}). Teleport to bind location.", guid.ToString(), x, y, z, o);
|
||||
|
||||
m_movementInfo.transport.Reset();
|
||||
RelocateToHomebind();
|
||||
@@ -2687,16 +2779,15 @@ namespace Game.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player (guidlow {0}) have problems with transport guid ({1}). Teleport to bind location.",
|
||||
guid.ToString(), transLowGUID);
|
||||
Log.outError(LogFilter.Player, "Player (guidlow {0}) have problems with transport guid ({1}). Teleport to bind location.", guid.ToString(), transguid);
|
||||
|
||||
RelocateToHomebind();
|
||||
}
|
||||
}
|
||||
// currently we do not support taxi in instance
|
||||
else if (!string.IsNullOrEmpty(taxi_nodes))
|
||||
else if (!taxi_path.IsEmpty())
|
||||
{
|
||||
instanceId = 0;
|
||||
instance_id = 0;
|
||||
|
||||
// Not finish taxi flight path
|
||||
if (m_bgData.HasTaxiPath())
|
||||
@@ -2704,7 +2795,7 @@ namespace Game.Entities
|
||||
for (int i = 0; i < 2; ++i)
|
||||
m_taxi.AddTaxiDestination(m_bgData.taxiPath[i]);
|
||||
}
|
||||
if (!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes, GetTeam()))
|
||||
if (!m_taxi.LoadTaxiDestinationsFromString(taxi_path, GetTeam()))
|
||||
{
|
||||
// problems with taxi path loading
|
||||
TaxiNodesRecord nodeEntry = null;
|
||||
@@ -2753,19 +2844,20 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// fix crash (because of if (Map* map = _FindMap(instanceId)) in MapInstanced.CreateInstance)
|
||||
if (instanceId != 0)
|
||||
if (instance_id != 0)
|
||||
{
|
||||
InstanceSave save = GetInstanceSave(mapId);
|
||||
if (save != null)
|
||||
if (save.GetInstanceId() != instanceId)
|
||||
instanceId = 0;
|
||||
if (save.GetInstanceId() != instance_id)
|
||||
instance_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// NOW player must have valid map
|
||||
// load the player's map here if it's not already loaded
|
||||
if (!map)
|
||||
map = Global.MapMgr.CreateMap(mapId, this, instanceId);
|
||||
map = Global.MapMgr.CreateMap(mapId, this, instance_id);
|
||||
|
||||
AreaTriggerStruct areaTrigger = null;
|
||||
bool check = false;
|
||||
|
||||
@@ -2802,7 +2894,7 @@ namespace Game.Entities
|
||||
areaTrigger = Global.ObjectMgr.GetGoBackTrigger(mapId);
|
||||
check = true;
|
||||
}
|
||||
else if (instanceId != 0 && Global.InstanceSaveMgr.GetInstanceSave(instanceId) == null) // ... and instance is reseted then look for entrance.
|
||||
else if (instance_id != 0 && Global.InstanceSaveMgr.GetInstanceSave(instance_id) == null) // ... and instance is reseted then look for entrance.
|
||||
{
|
||||
areaTrigger = Global.ObjectMgr.GetMapEntranceTrigger(mapId);
|
||||
check = true;
|
||||
@@ -2857,7 +2949,7 @@ namespace Game.Entities
|
||||
SaveRecallPosition();
|
||||
|
||||
long now = Time.UnixTime;
|
||||
long logoutTime = result.Read<int>(32);
|
||||
long logoutTime = logout_time;
|
||||
|
||||
// since last logout (in seconds)
|
||||
uint time_diff = (uint)(now - logoutTime);
|
||||
@@ -2870,32 +2962,30 @@ namespace Game.Entities
|
||||
|
||||
SetDrunkValue(newDrunkValue);
|
||||
|
||||
m_cinematic = result.Read<byte>(28);
|
||||
m_PlayedTimeTotal = result.Read<uint>(29);
|
||||
m_PlayedTimeLevel = result.Read<uint>(30);
|
||||
m_cinematic = cinematic;
|
||||
m_PlayedTimeTotal = totaltime;
|
||||
m_PlayedTimeLevel = leveltime;
|
||||
|
||||
SetTalentResetCost(result.Read<uint>(34));
|
||||
SetTalentResetTime(result.Read<uint>(35));
|
||||
SetTalentResetCost(resettalents_cost);
|
||||
SetTalentResetTime(resettalents_time);
|
||||
|
||||
m_taxi.LoadTaxiMask(result.Read<string>(27)); // must be before InitTaxiNodesForLevel
|
||||
m_taxi.LoadTaxiMask(taximask); // must be before InitTaxiNodesForLevel
|
||||
|
||||
PlayerExtraFlags extraflags = (PlayerExtraFlags)result.Read<uint>(42);
|
||||
|
||||
m_stableSlots = result.Read<byte>(43);
|
||||
m_stableSlots = stable_slots;
|
||||
if (m_stableSlots > 4)
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player can have not more {0} stable slots, but have in DB {1}", 4, m_stableSlots);
|
||||
m_stableSlots = 4;
|
||||
}
|
||||
|
||||
atLoginFlags = (AtLoginFlags)result.Read<uint>(44);
|
||||
atLoginFlags = (AtLoginFlags)at_login;
|
||||
|
||||
// Honor system
|
||||
// Update Honor kills data
|
||||
m_lastHonorUpdateTime = logoutTime;
|
||||
UpdateHonorFields();
|
||||
|
||||
m_deathExpireTime = result.Read<uint>(47);
|
||||
m_deathExpireTime = death_expire_time;
|
||||
if (m_deathExpireTime > now + PlayerConst.MaxDeathCount * PlayerConst.DeathExpireStep)
|
||||
m_deathExpireTime = now + PlayerConst.MaxDeathCount * PlayerConst.DeathExpireStep - 1;
|
||||
|
||||
@@ -2910,20 +3000,19 @@ namespace Game.Entities
|
||||
InitRunes();
|
||||
|
||||
// rest bonus can only be calculated after InitStatsForLevel()
|
||||
_restMgr.LoadRestBonus(RestTypes.XP, (PlayerRestState)result.Read<byte>(19), result.Read<float>(31));
|
||||
_restMgr.LoadRestBonus(RestTypes.XP, restState, rest_bonus);
|
||||
|
||||
// load skills after InitStatsForLevel because it triggering aura apply also
|
||||
_LoadSkills(holder.GetResult(PlayerLoginQueryLoad.Skills));
|
||||
UpdateSkillsForLevel();
|
||||
|
||||
SetNumRespecs(result.Read<byte>(76));
|
||||
SetPrimarySpecialization(result.Read<uint>(36));
|
||||
SetActiveTalentGroup(result.Read<byte>(64));
|
||||
SetNumRespecs(numRespecs);
|
||||
SetPrimarySpecialization(primarySpecialization);
|
||||
SetActiveTalentGroup(activeTalentGroup);
|
||||
ChrSpecializationRecord primarySpec = CliDB.ChrSpecializationStorage.LookupByKey(GetPrimarySpecialization());
|
||||
if (primarySpec == null || primarySpec.ClassID != (byte)GetClass() || GetActiveTalentGroup() >= PlayerConst.MaxSpecializations)
|
||||
ResetTalentSpecialization();
|
||||
|
||||
uint lootSpecId = result.Read<byte>(65);
|
||||
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(lootSpecId);
|
||||
if (chrSpec != null)
|
||||
{
|
||||
@@ -2986,11 +3075,10 @@ namespace Game.Entities
|
||||
|
||||
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
|
||||
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
|
||||
uint curTitle = result.Read<uint>(53);
|
||||
if (curTitle != 0 && !HasTitle(curTitle))
|
||||
curTitle = 0;
|
||||
if (chosenTitle != 0 && !HasTitle(chosenTitle))
|
||||
chosenTitle = 0;
|
||||
|
||||
SetChosenTitle(curTitle);
|
||||
SetChosenTitle(chosenTitle);
|
||||
|
||||
// has to be called after last Relocate() in Player.LoadFromDB
|
||||
SetFallInformation(0, GetPositionZ());
|
||||
@@ -3009,14 +3097,13 @@ namespace Game.Entities
|
||||
UpdateAllStats();
|
||||
|
||||
// restore remembered power/health values (but not more max values)
|
||||
uint savedHealth = result.Read<uint>(56);
|
||||
SetHealth(savedHealth > GetMaxHealth() ? GetMaxHealth() : savedHealth);
|
||||
SetHealth(health > GetMaxHealth() ? GetMaxHealth() : health);
|
||||
int loadedPowers = 0;
|
||||
for (PowerType i = 0; i < PowerType.Max; ++i)
|
||||
{
|
||||
if (Global.DB2Mgr.GetPowerIndexByClass(i, GetClass()) != (int)PowerType.Max)
|
||||
{
|
||||
uint savedPower = result.Read<uint>(56 + loadedPowers);
|
||||
uint savedPower = powers[loadedPowers];
|
||||
uint maxPower = m_unitData.MaxPower[loadedPowers];
|
||||
SetPower(i, (int)(savedPower > maxPower ? maxPower : savedPower));
|
||||
if (++loadedPowers >= (int)PowerType.MaxPerClass)
|
||||
@@ -3025,7 +3112,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
for (; loadedPowers < (int)PowerType.MaxPerClass; ++loadedPowers)
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Power, (int)loadedPowers), 0);
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Power, loadedPowers), 0);
|
||||
|
||||
SetPower(PowerType.LunarPower, 0);
|
||||
// Init rune recharge
|
||||
@@ -3054,7 +3141,7 @@ namespace Game.Entities
|
||||
case 1: SetGameMaster(true);
|
||||
break; // enable
|
||||
case 2: // save state
|
||||
if (extraflags.HasAnyFlag(PlayerExtraFlags.GMOn))
|
||||
if (extra_flags.HasAnyFlag(PlayerExtraFlags.GMOn))
|
||||
SetGameMaster(true);
|
||||
break;
|
||||
}
|
||||
@@ -3067,7 +3154,7 @@ namespace Game.Entities
|
||||
case 1:
|
||||
break; // visible
|
||||
case 2: // save state
|
||||
if (extraflags.HasAnyFlag(PlayerExtraFlags.GMInvisible))
|
||||
if (extra_flags.HasAnyFlag(PlayerExtraFlags.GMInvisible))
|
||||
SetGMVisible(false);
|
||||
break;
|
||||
}
|
||||
@@ -3080,7 +3167,7 @@ namespace Game.Entities
|
||||
case 1: SetGMChat(true);
|
||||
break; // enable
|
||||
case 2: // save state
|
||||
if (extraflags.HasAnyFlag(PlayerExtraFlags.GMChat))
|
||||
if (extra_flags.HasAnyFlag(PlayerExtraFlags.GMChat))
|
||||
SetGMChat(true);
|
||||
break;
|
||||
}
|
||||
@@ -3093,7 +3180,7 @@ namespace Game.Entities
|
||||
case 1: SetAcceptWhispers(true);
|
||||
break; // enable
|
||||
case 2: // save state
|
||||
if (extraflags.HasAnyFlag(PlayerExtraFlags.AcceptWhispers))
|
||||
if (extra_flags.HasAnyFlag(PlayerExtraFlags.AcceptWhispers))
|
||||
SetAcceptWhispers(true);
|
||||
break;
|
||||
}
|
||||
@@ -3118,16 +3205,16 @@ namespace Game.Entities
|
||||
holder.GetResult(PlayerLoginQueryLoad.GarrisonFollowerAbilities)))
|
||||
_garrison = garrison;
|
||||
|
||||
_InitHonorLevelOnLoadFromDB(result.Read<uint>(72), result.Read<uint>(73));
|
||||
_InitHonorLevelOnLoadFromDB(honor, honorLevel);
|
||||
|
||||
_restMgr.LoadRestBonus(RestTypes.Honor, (PlayerRestState)result.Read<byte>(74), result.Read<float>(75));
|
||||
_restMgr.LoadRestBonus(RestTypes.Honor, honorRestState, honorRestBonus);
|
||||
if (time_diff > 0)
|
||||
{
|
||||
//speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour)
|
||||
float bubble0 = 0.031f;
|
||||
//speed collect rest bonus in offline, in logout, in tavern, city (section/in hour)
|
||||
float bubble1 = 0.125f;
|
||||
float bubble = result.Read<byte>(33) > 0
|
||||
float bubble = is_logout_resting > 0
|
||||
? bubble1 * WorldConfig.GetFloatValue(WorldCfg.RateRestOfflineInTavernOrCity)
|
||||
: bubble0 * WorldConfig.GetFloatValue(WorldCfg.RateRestOfflineInWilderness);
|
||||
|
||||
@@ -3191,15 +3278,8 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, (byte)GetClass());
|
||||
stmt.AddValue(index++, (byte)m_playerData.NativeSex); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
|
||||
stmt.AddValue(index++, GetLevel());
|
||||
stmt.AddValue(index++, (uint)m_activePlayerData.XP);
|
||||
stmt.AddValue(index++, (uint)GetNativeSex());
|
||||
stmt.AddValue(index++, GetMoney());
|
||||
stmt.AddValue(index++, (byte)m_playerData.SkinID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.FaceID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.HairStyleID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.HairColorID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.FacialHairStyleID);
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
stmt.AddValue(index++, m_playerData.CustomDisplayOption[i]);
|
||||
stmt.AddValue(index++, GetInventorySlotCount());
|
||||
stmt.AddValue(index++, GetBankBagSlotCount());
|
||||
stmt.AddValue(index++, (byte)m_activePlayerData.RestInfo[(int)RestTypes.XP].StateID);
|
||||
@@ -3321,17 +3401,8 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, (byte)GetClass());
|
||||
stmt.AddValue(index++, (byte)m_playerData.NativeSex); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
|
||||
stmt.AddValue(index++, GetLevel());
|
||||
stmt.AddValue(index++, (uint)m_activePlayerData.XP);
|
||||
stmt.AddValue(index++, (uint)GetNativeSex());
|
||||
stmt.AddValue(index++, GetMoney());
|
||||
stmt.AddValue(index++, (byte)m_playerData.SkinID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.FaceID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.HairStyleID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.HairColorID);
|
||||
stmt.AddValue(index++, (byte)m_playerData.FacialHairStyleID);
|
||||
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
stmt.AddValue(index++, m_playerData.CustomDisplayOption[i]);
|
||||
|
||||
stmt.AddValue(index++, GetInventorySlotCount());
|
||||
stmt.AddValue(index++, GetBankBagSlotCount());
|
||||
stmt.AddValue(index++, (byte)m_activePlayerData.RestInfo[(int)RestTypes.XP].StateID);
|
||||
@@ -3485,6 +3556,7 @@ namespace Game.Entities
|
||||
if (m_mailsUpdated) //save mails only when needed
|
||||
_SaveMail(characterTransaction);
|
||||
|
||||
_SaveCustomizations(characterTransaction);
|
||||
_SaveBGData(characterTransaction);
|
||||
_SaveInventory(characterTransaction);
|
||||
_SaveVoidStorage(characterTransaction);
|
||||
@@ -3807,6 +3879,10 @@ namespace Game.Entities
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_CUSTOMIZATIONS);
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_PLAYER_ACCOUNT_DATA);
|
||||
stmt.AddValue(0, guid);
|
||||
trans.Append(stmt);
|
||||
|
||||
@@ -196,6 +196,7 @@ namespace Game.Entities
|
||||
byte m_cinematic;
|
||||
|
||||
uint m_movie;
|
||||
bool m_customizationsChanged;
|
||||
|
||||
SpecializationInfo _specializationInfo;
|
||||
public List<ObjectGuid> m_clientGUIDs = new List<ObjectGuid>();
|
||||
|
||||
@@ -32,6 +32,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Game.BattleFields;
|
||||
using Framework.Dynamic;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
@@ -3848,6 +3849,8 @@ namespace Game.Entities
|
||||
if (guild != null)
|
||||
guild.AddGuildNews(GuildNews.ItemPurchased, GetGUID(), 0, item);
|
||||
}
|
||||
|
||||
UpdateCriteria(CriteriaTypes.BoughtItemFromVendor, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5186,9 +5189,12 @@ namespace Game.Entities
|
||||
return InventoryResult.ClientLockedOut;
|
||||
}
|
||||
|
||||
ScalingStatDistributionRecord ssd = CliDB.ScalingStatDistributionStorage.LookupByKey(pItem.GetScalingStatDistribution());
|
||||
ContentTuningLevels? requiredLevels = null;
|
||||
// check allowed level (extend range to upper values if MaxLevel more or equal max player level, this let GM set high level with 1...max range items)
|
||||
if (ssd != null && ssd.MaxLevel < WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel) && ssd.MaxLevel < GetLevel() && Global.DB2Mgr.GetHeirloomByItemId(pProto.GetId()) == null)
|
||||
if (pItem.GetQuality() == ItemQuality.Heirloom)
|
||||
requiredLevels = Global.DB2Mgr.GetContentTuningData(pItem.GetScalingContentTuningId(), 0, true);
|
||||
|
||||
if (requiredLevels.HasValue && requiredLevels.Value.MaxLevel < SharedConst.DefaultMaxLevel && requiredLevels.Value.MaxLevel < GetLevel() && Global.DB2Mgr.GetHeirloomByItemId(pProto.GetId()) == null)
|
||||
return InventoryResult.NotEquippable;
|
||||
|
||||
byte eslot = FindEquipSlot(pProto, slot, swap);
|
||||
|
||||
@@ -144,6 +144,8 @@ namespace Game.Entities
|
||||
_restMgr.SetRestFlag(RestFlag.FactionArea);
|
||||
else
|
||||
_restMgr.RemoveRestFlag(RestFlag.FactionArea);
|
||||
|
||||
UpdateCriteria(CriteriaTypes.TravelledToArea, newArea);
|
||||
}
|
||||
|
||||
public void UpdateZone(uint newZone, uint newArea)
|
||||
|
||||
@@ -49,14 +49,18 @@ namespace Game.Entities
|
||||
|
||||
public int GetQuestMinLevel(Quest quest)
|
||||
{
|
||||
if (quest.Level == -1 && quest.ScalingFactionGroup != 0)
|
||||
var questLevels = Global.DB2Mgr.GetContentTuningData(quest.ContentTuningId, m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (questLevels.HasValue)
|
||||
{
|
||||
ChrRacesRecord race = CliDB.ChrRacesStorage.LookupByKey(GetRace());
|
||||
FactionTemplateRecord raceFaction = CliDB.FactionTemplateStorage.LookupByKey(race.FactionID);
|
||||
if (raceFaction == null || raceFaction.FactionGroup != quest.ScalingFactionGroup)
|
||||
return quest.MaxScalingLevel;
|
||||
if (raceFaction == null || raceFaction.FactionGroup != CliDB.ContentTuningStorage.LookupByKey(quest.ContentTuningId).GetScalingFactionGroup())
|
||||
return questLevels.Value.MaxLevel;
|
||||
|
||||
return questLevels.Value.MinLevelWithDelta;
|
||||
}
|
||||
return quest.MinLevel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetQuestLevel(Quest quest)
|
||||
@@ -64,16 +68,18 @@ namespace Game.Entities
|
||||
if (quest == null)
|
||||
return 0;
|
||||
|
||||
if (quest.Level == -1)
|
||||
var questLevels = Global.DB2Mgr.GetContentTuningData(quest.ContentTuningId, m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (questLevels.HasValue)
|
||||
{
|
||||
int minLevel = GetQuestMinLevel(quest);
|
||||
int maxLevel = quest.MaxScalingLevel;
|
||||
int maxLevel = questLevels.Value.MaxLevel;
|
||||
int level = (int)GetLevel();
|
||||
if (level >= minLevel)
|
||||
return Math.Min(level, maxLevel);
|
||||
return minLevel;
|
||||
}
|
||||
return quest.Level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int GetRewardedQuestCount() { return m_RewardedQuests.Count; }
|
||||
@@ -1153,6 +1159,7 @@ namespace Game.Entities
|
||||
|
||||
UpdateCriteria(CriteriaTypes.CompleteQuestCount);
|
||||
UpdateCriteria(CriteriaTypes.CompleteQuest, quest.Id);
|
||||
UpdateCriteria(CriteriaTypes.CompleteQuestAccumulate, 1);
|
||||
|
||||
// make full db save
|
||||
SaveToDB(false);
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Game.Entities
|
||||
|
||||
m_zoneUpdateId = 0xffffffff;
|
||||
m_nextSave = WorldConfig.GetUIntValue(WorldCfg.IntervalSave);
|
||||
m_customizationsChanged = false;
|
||||
|
||||
SetGroupInvite(null);
|
||||
|
||||
@@ -184,7 +185,7 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ValidateAppearance(createInfo.RaceId, createInfo.ClassId, createInfo.Sex, createInfo.HairStyle, createInfo.HairColor, createInfo.Face, createInfo.FacialHairStyle, createInfo.Skin, createInfo.CustomDisplay, true))
|
||||
if (!GetSession().ValidateAppearance(createInfo.RaceId, createInfo.ClassId, createInfo.Sex, createInfo.Customizations))
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player.Create: Possible hacking-attempt: Account {0} tried creating a character named '{1}' with invalid appearance attributes - refusing to do so",
|
||||
GetSession().GetAccountId(), GetName());
|
||||
@@ -223,14 +224,7 @@ namespace Game.Entities
|
||||
|
||||
SetWatchedFactionIndex(0xFFFFFFFF);
|
||||
|
||||
SetSkinId(createInfo.Skin);
|
||||
SetFaceId(createInfo.Face);
|
||||
SetHairStyleId(createInfo.HairStyle);
|
||||
SetHairColorId(createInfo.HairColor);
|
||||
SetFacialHairStyleId(createInfo.FacialHairStyle);
|
||||
for (byte i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
SetCustomDisplayOption(i, createInfo.CustomDisplay[i]);
|
||||
|
||||
SetCustomizations(createInfo.Customizations);
|
||||
SetRestState(RestTypes.XP, ((GetSession().IsARecruiter() || GetSession().GetRecruiterId() != 0) ? PlayerRestState.RAFLinked : PlayerRestState.NotRAFLinked));
|
||||
SetRestState(RestTypes.Honor, PlayerRestState.NotRAFLinked);
|
||||
SetNativeSex(createInfo.Sex);
|
||||
@@ -308,46 +302,8 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// original items
|
||||
CharStartOutfitRecord oEntry = Global.DB2Mgr.GetCharStartOutfitEntry((byte)createInfo.RaceId, (byte)createInfo.ClassId, (byte)createInfo.Sex);
|
||||
if (oEntry != null)
|
||||
{
|
||||
for (int j = 0; j < ItemConst.MaxOutfitItems - 1; ++j)
|
||||
{
|
||||
if (oEntry.ItemID[j] <= 0)
|
||||
continue;
|
||||
|
||||
uint itemId = (uint)oEntry.ItemID[j];
|
||||
|
||||
ItemTemplate iProto = Global.ObjectMgr.GetItemTemplate(itemId);
|
||||
if (iProto == null)
|
||||
continue;
|
||||
|
||||
// BuyCount by default
|
||||
uint count = iProto.GetBuyCount();
|
||||
|
||||
// special amount for food/drink
|
||||
if (iProto.GetClass() == ItemClass.Consumable && iProto.GetSubClass() == (uint)ItemSubClassConsumable.FoodDrink)
|
||||
{
|
||||
if (!iProto.Effects.Empty())
|
||||
{
|
||||
switch (iProto.Effects[0].SpellCategoryID)
|
||||
{
|
||||
case 11: // food
|
||||
count = (uint)(GetClass() == Class.Deathknight ? 10 : 4);
|
||||
break;
|
||||
case 59: // drink
|
||||
count = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (iProto.GetMaxStackSize() < count)
|
||||
count = iProto.GetMaxStackSize();
|
||||
}
|
||||
StoreNewItemInBestSlots(itemId, count);
|
||||
}
|
||||
}
|
||||
foreach (var item in info.item)
|
||||
StoreNewItemInBestSlots(item.item_id, item.item_amount);
|
||||
foreach (PlayerCreateInfoItem initialItem in info.item)
|
||||
StoreNewItemInBestSlots(initialItem.item_id, initialItem.item_amount);
|
||||
|
||||
// bags and main-hand weapon must equipped at this moment
|
||||
// now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon)
|
||||
@@ -1193,7 +1149,7 @@ namespace Game.Entities
|
||||
FactionRecord factionEntry = CliDB.FactionStorage.LookupByKey(currency.FactionID);
|
||||
if (factionEntry != null)
|
||||
{
|
||||
if (currency.Flags.HasAnyFlag((uint)CurrencyFlags.HighPrecision))
|
||||
if (currency.Flags[0].HasAnyFlag((int)CurrencyFlags.HighPrecision))
|
||||
count /= 100;
|
||||
GetReputationMgr().ModifyReputation(factionEntry, count, false, true);
|
||||
return;
|
||||
@@ -1582,8 +1538,12 @@ namespace Game.Entities
|
||||
{
|
||||
LFGDungeonsRecord dungeon = Global.DB2Mgr.GetLfgDungeon(map.GetId(), map.GetDifficultyID());
|
||||
if (dungeon != null)
|
||||
if (dungeon.TargetLevel == 80)
|
||||
ChampioningFaction = GetChampioningFaction();
|
||||
{
|
||||
var dungeonLevels = Global.DB2Mgr.GetContentTuningData(dungeon.ContentTuningID, m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (dungeonLevels.HasValue)
|
||||
if (dungeonLevels.Value.TargetLevelMax == Global.ObjectMgr.GetMaxLevelForExpansion(Expansion.WrathOfTheLichKing))
|
||||
ChampioningFaction = GetChampioningFaction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2613,6 +2573,9 @@ namespace Game.Entities
|
||||
if (channel.Flags.HasAnyFlag(ChannelDBCFlags.GuildReq) && GetGuildId() != 0)
|
||||
return false;
|
||||
|
||||
if (channel.Flags.HasAnyFlag(ChannelDBCFlags.NoClientJoin))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
public void JoinedChannel(Channel c)
|
||||
@@ -2658,6 +2621,9 @@ namespace Game.Entities
|
||||
|
||||
foreach (var channelEntry in CliDB.ChatChannelsStorage.Values)
|
||||
{
|
||||
if (!channelEntry.Flags.HasAnyFlag(ChannelDBCFlags.Initial))
|
||||
continue;
|
||||
|
||||
Channel usedChannel = null;
|
||||
foreach (var channel in m_channels)
|
||||
{
|
||||
@@ -3467,51 +3433,27 @@ namespace Game.Entities
|
||||
SendBattlefieldWorldStates();
|
||||
}
|
||||
|
||||
public uint GetBarberShopCost(BarberShopStyleRecord newHairStyle, uint newHairColor, BarberShopStyleRecord newFacialHair, BarberShopStyleRecord newSkin, BarberShopStyleRecord newFace, Array<BarberShopStyleRecord> newCustomDisplay)
|
||||
public long GetBarberShopCost(List<ChrCustomizationChoice> newCustomizations)
|
||||
{
|
||||
byte hairstyle = m_playerData.HairStyleID;
|
||||
byte haircolor = m_playerData.HairColorID;
|
||||
byte facialhair = m_playerData.FacialHairStyleID;
|
||||
byte skincolor = m_playerData.SkinID;
|
||||
byte face = m_playerData.FaceID;
|
||||
|
||||
Array<byte> customDisplay = new Array<byte>(PlayerConst.CustomDisplaySize);
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
customDisplay[i] = m_playerData.CustomDisplayOption[i];
|
||||
|
||||
if ((hairstyle == newHairStyle.Data) &&
|
||||
(haircolor == newHairColor) &&
|
||||
(facialhair == newFacialHair.Data) &&
|
||||
(newSkin == null || (newSkin.Data == skincolor)) &&
|
||||
(newFace == null || (newFace.Data == face)) &&
|
||||
(newCustomDisplay[0] == null || (newCustomDisplay[0].Data == customDisplay[0])) &&
|
||||
(newCustomDisplay[1] == null || (newCustomDisplay[1].Data == customDisplay[1])) &&
|
||||
(newCustomDisplay[2] == null || (newCustomDisplay[2].Data == customDisplay[2])))
|
||||
return 0;
|
||||
|
||||
GtBarberShopCostBaseRecord bsc = CliDB.BarberShopCostBaseGameTable.GetRow(GetLevel());
|
||||
if (bsc == null) // shouldn't happen
|
||||
return 0xFFFFFFFF;
|
||||
return 0;
|
||||
|
||||
uint cost = 0;
|
||||
if (hairstyle != newHairStyle.Data)
|
||||
cost += (uint)(bsc.Cost * newHairStyle.CostModifier);
|
||||
long cost = 0;
|
||||
foreach (ChrCustomizationChoice newChoice in newCustomizations)
|
||||
{
|
||||
int currentCustomizationIndex = m_playerData.Customizations.FindIndexIf(currentCustomization =>
|
||||
{
|
||||
return currentCustomization.ChrCustomizationOptionID == newChoice.ChrCustomizationOptionID;
|
||||
});
|
||||
|
||||
if ((haircolor != newHairColor) && (hairstyle == newHairStyle.Data))
|
||||
cost += (uint)(bsc.Cost * 0.5f); // +1/2 of price
|
||||
|
||||
if (facialhair != newFacialHair.Data)
|
||||
cost += (uint)(bsc.Cost * newFacialHair.CostModifier);
|
||||
|
||||
if (newSkin != null && skincolor != newSkin.Data)
|
||||
cost += (uint)(bsc.Cost * newSkin.CostModifier);
|
||||
|
||||
if (newFace != null && face != newFace.Data)
|
||||
cost += (uint)(bsc.Cost * newFace.CostModifier);
|
||||
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
if (newCustomDisplay[i] != null && customDisplay[i] != newCustomDisplay[i].Data)
|
||||
cost += (uint)(bsc.Cost * newCustomDisplay[i].CostModifier);
|
||||
if (currentCustomizationIndex == -1 || m_playerData.Customizations[currentCustomizationIndex].ChrCustomizationChoiceID != newChoice.ChrCustomizationChoiceID)
|
||||
{
|
||||
ChrCustomizationOptionRecord customizationOption = CliDB.ChrCustomizationOptionStorage.LookupByKey(newChoice.ChrCustomizationOptionID);
|
||||
if (customizationOption != null)
|
||||
cost += (long)(bsc.Cost * customizationOption.BarberShopCostModifier);
|
||||
}
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
@@ -3950,139 +3892,10 @@ namespace Game.Entities
|
||||
return null;
|
||||
}
|
||||
|
||||
static uint GetSelectionFromContext(uint context, Class playerClass)
|
||||
{
|
||||
switch (context)
|
||||
{
|
||||
case 1:
|
||||
if (playerClass == Class.Deathknight)
|
||||
return 1;
|
||||
if (playerClass == Class.DemonHunter)
|
||||
return 3;
|
||||
return 0;
|
||||
case 2:
|
||||
if (playerClass == Class.Deathknight)
|
||||
return 5;
|
||||
if (playerClass == Class.DemonHunter)
|
||||
return 6;
|
||||
return 4;
|
||||
case 3:
|
||||
return 7;
|
||||
case 4:
|
||||
if (playerClass == Class.Deathknight)
|
||||
return 9;
|
||||
if (playerClass == Class.DemonHunter)
|
||||
return 10;
|
||||
return 8;
|
||||
default:
|
||||
if (playerClass == Class.Deathknight)
|
||||
return 1;
|
||||
if (playerClass == Class.DemonHunter)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ComponentFlagsMatch(CharSectionsRecord entry, uint selection)
|
||||
{
|
||||
switch (selection)
|
||||
{
|
||||
case 0:
|
||||
if (!entry.Flags.HasAnyFlag((short)1))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)0x2C);
|
||||
case 1:
|
||||
if (!entry.Flags.HasAnyFlag((short)1))
|
||||
return false;
|
||||
if (!entry.Flags.HasAnyFlag((short)0x94))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)8);
|
||||
case 2:
|
||||
if (!entry.Flags.HasAnyFlag((short)1))
|
||||
return false;
|
||||
if (!entry.Flags.HasAnyFlag((short)0x70))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)8);
|
||||
case 3:
|
||||
if (!entry.Flags.HasAnyFlag((short)1))
|
||||
return false;
|
||||
if (!entry.Flags.HasAnyFlag((short)0x20))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)8);
|
||||
case 4:
|
||||
case 8:
|
||||
if (!entry.Flags.HasAnyFlag((short)3))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)0x2C);
|
||||
case 5:
|
||||
case 9:
|
||||
if (!entry.Flags.HasAnyFlag((short)3))
|
||||
return false;
|
||||
if (!entry.Flags.HasAnyFlag((short)0x94))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)8);
|
||||
case 6:
|
||||
case 10:
|
||||
if (!entry.Flags.HasAnyFlag((short)3))
|
||||
return false;
|
||||
if (!entry.Flags.HasAnyFlag((short)0x70))
|
||||
return false;
|
||||
return !entry.Flags.HasAnyFlag((short)8);
|
||||
case 7:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsSectionFlagValid(CharSectionsRecord entry, Class class_, bool create)
|
||||
{
|
||||
if (create)
|
||||
return ComponentFlagsMatch(entry, GetSelectionFromContext(0, class_));
|
||||
|
||||
return ComponentFlagsMatch(entry, GetSelectionFromContext(2, class_));
|
||||
}
|
||||
static bool IsSectionValid(Race race, Class class_, Gender gender, CharBaseSectionVariation variation, byte variationIndex, byte colorIndex, bool create)
|
||||
{
|
||||
CharSectionsRecord section = Global.DB2Mgr.GetCharSectionEntry(race, gender, variation, variationIndex, colorIndex);
|
||||
if (section != null)
|
||||
return IsSectionFlagValid(section, class_, create);
|
||||
|
||||
return false;
|
||||
}
|
||||
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((1 << ((int)_race - 1)) & (int)Race.RaceMaskAllPlayable); }
|
||||
|
||||
public static bool ValidateAppearance(Race race, Class class_, Gender gender, byte hairID, byte hairColor, byte faceID, byte facialHairId, byte skinColor, Array<byte> customDisplay, bool create = false)
|
||||
{
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.Skin, 0, skinColor, create))
|
||||
return false;
|
||||
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.Face, faceID, skinColor, create))
|
||||
return false;
|
||||
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.Hair, hairID, hairColor, create))
|
||||
return false;
|
||||
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.FacialHair, facialHairId, hairColor, create))
|
||||
if (Global.DB2Mgr.HasCharSections(race, gender, CharBaseSectionVariation.FacialHair) || !Global.DB2Mgr.HasCharacterFacialHairStyle(race, gender, facialHairId))
|
||||
return false;
|
||||
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.CustomDisplay1, customDisplay[0], 0, create))
|
||||
return false;
|
||||
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.CustomDisplay2, customDisplay[1], 0, create))
|
||||
return false;
|
||||
|
||||
if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation.CustomDisplay3, customDisplay[2], 0, create))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnCombatExit()
|
||||
{
|
||||
UpdatePotionCooldown();
|
||||
@@ -4594,12 +4407,8 @@ namespace Game.Entities
|
||||
flags |= CorpseFlags.FFAPvP;
|
||||
|
||||
corpse.SetRace(GetRace());
|
||||
corpse.SetSex((Gender)(byte)m_playerData.NativeSex);
|
||||
corpse.SetSkin(m_playerData.SkinID);
|
||||
corpse.SetFace(m_playerData.FaceID);
|
||||
corpse.SetHairStyle(m_playerData.HairStyleID);
|
||||
corpse.SetHairColor(m_playerData.HairColorID);
|
||||
corpse.SetFacialHairStyle(m_playerData.FacialHairStyleID);
|
||||
corpse.SetSex(GetNativeSex());
|
||||
corpse.SetCustomizations(m_playerData.Customizations);
|
||||
corpse.SetFlags(flags);
|
||||
corpse.SetDisplayId(GetNativeDisplayId());
|
||||
corpse.SetFactionTemplate(CliDB.ChrRacesStorage.LookupByKey(GetRace()).FactionID);
|
||||
@@ -5475,8 +5284,7 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
byte gender = m_playerData.NativeSex;
|
||||
switch ((Gender)gender)
|
||||
switch (GetNativeSex())
|
||||
{
|
||||
case Gender.Female:
|
||||
SetDisplayId(info.DisplayId_f);
|
||||
@@ -5487,7 +5295,7 @@ namespace Game.Entities
|
||||
SetNativeDisplayId(info.DisplayId_m);
|
||||
break;
|
||||
default:
|
||||
Log.outError(LogFilter.Player, "Player {0} ({1}) has invalid gender {2}", GetName(), GetGUID().ToString(), (Gender)gender);
|
||||
Log.outError(LogFilter.Player, "Player {0} ({1}) has invalid gender {2}", GetName(), GetGUID().ToString(), GetNativeSex());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5883,13 +5691,13 @@ namespace Game.Entities
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePos), 0);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingPercent), 1.0f);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePercent), 1.0f);
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModPeriodicHealingDonePercent), 1.0f);
|
||||
for (byte i = 0; i < 7; ++i)
|
||||
for (byte i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
{
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDoneNeg, i), 0);
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePos, i), 0);
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePercent, i), 1.0f);
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePercent, i), 1.0f);
|
||||
}
|
||||
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModSpellPowerPercent), 1.0f);
|
||||
@@ -6324,7 +6132,8 @@ namespace Game.Entities
|
||||
|
||||
UpdateCriteria(CriteriaTypes.ExploreArea, GetAreaId());
|
||||
|
||||
if (areaEntry.ExplorationLevel > 0)
|
||||
var areaLevels = Global.DB2Mgr.GetContentTuningData(areaEntry.ContentTuningID, m_playerData.CtrOptions.GetValue().ContentTuningConditionMask);
|
||||
if (areaLevels.HasValue)
|
||||
{
|
||||
if (GetLevel() >= WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel))
|
||||
{
|
||||
@@ -6332,7 +6141,8 @@ namespace Game.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
int diff = (int)(GetLevel() - areaEntry.ExplorationLevel);
|
||||
ushort areaLevel = (ushort)Math.Min(Math.Max((ushort)GetLevel(), areaLevels.Value.MinLevel), areaLevels.Value.MaxLevel);
|
||||
int diff = (int)(GetLevel()) - areaLevel;
|
||||
uint XP = 0;
|
||||
if (diff < -5)
|
||||
{
|
||||
@@ -6344,11 +6154,11 @@ namespace Game.Entities
|
||||
if (exploration_percent < 0)
|
||||
exploration_percent = 0;
|
||||
|
||||
XP = (uint)(Global.ObjectMgr.GetBaseXP((byte)areaEntry.ExplorationLevel) * exploration_percent / 100 * WorldConfig.GetFloatValue(WorldCfg.RateXpExplore));
|
||||
XP = (uint)(Global.ObjectMgr.GetBaseXP(areaLevel) * exploration_percent / 100 * WorldConfig.GetFloatValue(WorldCfg.RateXpExplore));
|
||||
}
|
||||
else
|
||||
{
|
||||
XP = (uint)(Global.ObjectMgr.GetBaseXP((byte)areaEntry.ExplorationLevel) * WorldConfig.GetFloatValue(WorldCfg.RateXpExplore));
|
||||
XP = (uint)(Global.ObjectMgr.GetBaseXP(areaLevel) * WorldConfig.GetFloatValue(WorldCfg.RateXpExplore));
|
||||
}
|
||||
|
||||
GiveXP(XP, null);
|
||||
@@ -7477,17 +7287,40 @@ namespace Game.Entities
|
||||
public void RemovePlayerFlagEx(PlayerFlagsEx flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.PlayerFlagsEx), (uint)flags); }
|
||||
public void SetPlayerFlagsEx(PlayerFlagsEx flags) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.PlayerFlagsEx), (uint)flags); }
|
||||
|
||||
public void SetSkinId(byte skinId) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.SkinID), skinId); }
|
||||
public void SetFaceId(byte faceId) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.FaceID), faceId); }
|
||||
public void SetHairStyleId(byte hairStyleId) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.HairStyleID), hairStyleId); }
|
||||
public void SetHairColorId(byte hairColorId) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.HairColorID), hairColorId); }
|
||||
public void SetFacialHairStyleId(byte facialHairStyleId) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.FacialHairStyleID), facialHairStyleId); }
|
||||
public uint GetCustomizationChoice(uint chrCustomizationOptionId)
|
||||
{
|
||||
int choiceIndex = m_playerData.Customizations.FindIndexIf(choice =>
|
||||
{
|
||||
return choice.ChrCustomizationOptionID == chrCustomizationOptionId;
|
||||
});
|
||||
|
||||
if (choiceIndex >= 0)
|
||||
return m_playerData.Customizations[choiceIndex].ChrCustomizationChoiceID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void SetCustomizations(List<ChrCustomizationChoice> customizations, bool markChanged = true)
|
||||
{
|
||||
if (markChanged)
|
||||
m_customizationsChanged = true;
|
||||
|
||||
ClearDynamicUpdateFieldValues(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.Customizations));
|
||||
foreach (var customization in customizations)
|
||||
{
|
||||
ChrCustomizationChoice newChoice = new ChrCustomizationChoice();
|
||||
newChoice.ChrCustomizationOptionID = customization.ChrCustomizationOptionID;
|
||||
newChoice.ChrCustomizationChoiceID = customization.ChrCustomizationChoiceID;
|
||||
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.Customizations), newChoice);
|
||||
}
|
||||
}
|
||||
|
||||
public Gender GetNativeSex() { return (Gender)(byte)m_playerData.NativeSex; }
|
||||
public void SetNativeSex(Gender sex) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.NativeSex), (byte)sex); }
|
||||
public void SetPvpTitle(byte pvpTitle) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.PvpTitle), pvpTitle); }
|
||||
public void SetArenaFaction(byte arenaFaction) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.ArenaFaction), arenaFaction); }
|
||||
public void ApplyModFakeInebriation(int mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.FakeInebriation), mod, apply); }
|
||||
public void SetVirtualPlayerRealm(uint virtualRealmAddress) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.VirtualPlayerRealm), virtualRealmAddress); }
|
||||
public void SetCustomDisplayOption(int slot, byte customDisplayOption) { SetUpdateFieldValue(ref m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.CustomDisplayOption, slot), customDisplayOption); }
|
||||
|
||||
public void AddHeirloom(uint itemId, uint flags)
|
||||
{
|
||||
@@ -7537,9 +7370,9 @@ namespace Game.Entities
|
||||
public void ApplyModOverrideAPBySpellPowerPercent(float mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OverrideAPBySpellPowerPercent), mod, apply); }
|
||||
|
||||
public bool HasPlayerLocalFlag(PlayerLocalFlags flags) { return (m_activePlayerData.LocalFlags & (int)flags) != 0; }
|
||||
public void AddPlayerLocalFlag(PlayerLocalFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LocalFlags), (int)flags); }
|
||||
public void RemovePlayerLocalFlag(PlayerLocalFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LocalFlags), (int)flags); }
|
||||
public void SetPlayerLocalFlags(PlayerLocalFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LocalFlags), (int)flags); }
|
||||
public void AddPlayerLocalFlag(PlayerLocalFlags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LocalFlags), (uint)flags); }
|
||||
public void RemovePlayerLocalFlag(PlayerLocalFlags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LocalFlags), (uint)flags); }
|
||||
public void SetPlayerLocalFlags(PlayerLocalFlags flags) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.LocalFlags), (uint)flags); }
|
||||
|
||||
public byte GetNumRespecs() { return m_activePlayerData.NumRespecs; }
|
||||
public void SetNumRespecs(byte numRespecs) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.NumRespecs), numRespecs); }
|
||||
|
||||
@@ -114,7 +114,11 @@ namespace Game.Entities
|
||||
if (rested_bonus > xp) // max rested_bonus == xp or (r+x) = 200% xp
|
||||
rested_bonus = xp;
|
||||
|
||||
SetRestBonus(restType, GetRestBonus(restType) - rested_bonus);
|
||||
uint rested_loss = rested_bonus;
|
||||
if (restType == RestTypes.XP)
|
||||
MathFunctions.AddPct(ref rested_loss, _player.GetTotalAuraModifier(AuraType.ModRestedXpConsumption));
|
||||
|
||||
SetRestBonus(restType, GetRestBonus(restType) - rested_loss);
|
||||
|
||||
Log.outDebug(LogFilter.Player, "RestMgr.GetRestBonus: Player '{0}' ({1}) gain {2} xp (+{3} Rested Bonus). Rested points={4}",
|
||||
_player.GetGUID().ToString(), _player.GetName(), xp + rested_bonus, rested_bonus, GetRestBonus(restType));
|
||||
|
||||
@@ -1493,7 +1493,8 @@ namespace Game.Entities
|
||||
foreach (AuraEffect auraEffect in GetAuraEffectsByType(AuraType.ModHealingDonePercent))
|
||||
MathFunctions.AddPct(ref value, auraEffect.GetAmount());
|
||||
|
||||
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePercent), value);
|
||||
for (int i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
SetUpdateFieldStatValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModHealingDonePercent, i), value);
|
||||
}
|
||||
|
||||
void UpdateCorruption()
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Game.Entities
|
||||
// Get spell cast by totem
|
||||
SpellInfo totemSpell = Global.SpellMgr.GetSpellInfo(GetSpell(), GetMap().GetDifficultyID());
|
||||
if (totemSpell != null)
|
||||
if (totemSpell.CalcCastTime(GetLevel()) != 0) // If spell has cast time . its an active totem
|
||||
if (totemSpell.CalcCastTime() != 0) // If spell has cast time -> its an active totem
|
||||
m_type = TotemType.Active;
|
||||
|
||||
m_duration = duration;
|
||||
|
||||
@@ -516,7 +516,14 @@ namespace Game.Entities
|
||||
|
||||
Player thisPlayer = ToPlayer();
|
||||
if (thisPlayer != null)
|
||||
return thisPlayer.m_activePlayerData.ModHealingDonePercent;
|
||||
{
|
||||
float maxModDamagePercentSchool = 0.0f;
|
||||
for (int i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
if (((int)spellProto.GetSchoolMask() & (1 << i)) != 0)
|
||||
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, thisPlayer.m_activePlayerData.ModHealingDonePercent[i]);
|
||||
|
||||
return maxModDamagePercentSchool;
|
||||
}
|
||||
|
||||
float DoneTotalMod = 1.0f;
|
||||
|
||||
@@ -1201,8 +1208,10 @@ namespace Game.Entities
|
||||
{
|
||||
// mainly for DoTs which are 3500 here otherwise
|
||||
int OriginalCastTime = spellProto.CalcCastTime();
|
||||
if (OriginalCastTime > 7000) OriginalCastTime = 7000;
|
||||
if (OriginalCastTime < 1500) OriginalCastTime = 1500;
|
||||
if (OriginalCastTime > 7000)
|
||||
OriginalCastTime = 7000;
|
||||
if (OriginalCastTime < 1500)
|
||||
OriginalCastTime = 1500;
|
||||
// Portion to Over Time
|
||||
float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f));
|
||||
|
||||
@@ -2068,7 +2077,7 @@ namespace Game.Entities
|
||||
InterruptSpell(CurrentSpellTypes.AutoRepeat);
|
||||
m_AutoRepeatFirstCast = true;
|
||||
}
|
||||
if (pSpell.m_spellInfo.CalcCastTime(GetLevel()) > 0)
|
||||
if (pSpell.m_spellInfo.CalcCastTime() > 0)
|
||||
AddUnitState(UnitState.Casting);
|
||||
|
||||
break;
|
||||
@@ -2152,26 +2161,19 @@ namespace Game.Entities
|
||||
public uint SpellCriticalDamageBonus(SpellInfo spellProto, uint damage, Unit victim = null)
|
||||
{
|
||||
// Calculate critical bonus
|
||||
int crit_bonus = (int)damage;
|
||||
int crit_bonus = (int)damage * 2;
|
||||
float crit_mod = 0.0f;
|
||||
|
||||
switch (spellProto.DmgClass)
|
||||
{
|
||||
case SpellDmgClass.Melee: // for melee based spells is 100%
|
||||
case SpellDmgClass.Ranged:
|
||||
// @todo write here full calculation for melee/ranged spells
|
||||
crit_bonus += (int)damage;
|
||||
break;
|
||||
default:
|
||||
crit_bonus += (int)damage / 2; // for spells is 50%
|
||||
break;
|
||||
}
|
||||
|
||||
crit_mod += (GetTotalAuraMultiplierByMiscMask(AuraType.ModCritDamageBonus, (uint)spellProto.GetSchoolMask()) - 1.0f) * 100;
|
||||
|
||||
if (crit_bonus != 0)
|
||||
MathFunctions.AddPct(ref crit_bonus, (int)crit_mod);
|
||||
|
||||
MathFunctions.AddPct(ref crit_bonus, victim.GetTotalAuraModifier(AuraType.ModCriticalDamageTakenFromCaster, aurEff =>
|
||||
{
|
||||
return aurEff.GetCasterGUID() == GetGUID();
|
||||
}));
|
||||
|
||||
crit_bonus -= (int)damage;
|
||||
|
||||
if (damage > crit_bonus)
|
||||
|
||||
@@ -1207,7 +1207,7 @@ namespace Game.Entities
|
||||
if (artifactAura != null)
|
||||
{
|
||||
Item artifact = ToPlayer().GetItemByGuid(artifactAura.GetCastItemGUID());
|
||||
if (artifact)
|
||||
if (artifact != null)
|
||||
{
|
||||
ArtifactAppearanceRecord artifactAppearance = CliDB.ArtifactAppearanceStorage.LookupByKey(artifact.GetModifier(ItemModifier.ArtifactAppearanceId));
|
||||
if (artifactAppearance != null)
|
||||
@@ -1216,398 +1216,84 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
byte hairColor = thisPlayer.m_playerData.HairColorID;
|
||||
byte skinColor = thisPlayer.m_playerData.SkinID;
|
||||
ShapeshiftFormModelData formModelData = Global.DB2Mgr.GetShapeshiftFormModelData(GetRace(), thisPlayer.GetNativeSex(), form);
|
||||
if (formModelData != null)
|
||||
{
|
||||
bool useRandom = false;
|
||||
switch (form)
|
||||
{
|
||||
case ShapeShiftForm.CatForm:
|
||||
useRandom = HasAura(210333);
|
||||
break; // Glyph of the Feral Chameleon
|
||||
case ShapeShiftForm.TravelForm:
|
||||
useRandom = HasAura(344336);
|
||||
break; // Glyph of the Swift Chameleon
|
||||
case ShapeShiftForm.AquaticForm:
|
||||
useRandom = HasAura(344338);
|
||||
break; // Glyph of the Aquatic Chameleon
|
||||
case ShapeShiftForm.BearForm:
|
||||
useRandom = HasAura(107059);
|
||||
break; // Glyph of the Ursol Chameleon
|
||||
case ShapeShiftForm.FlightForm:
|
||||
useRandom = HasAura(344342);
|
||||
break; // Glyph of the Aerial Chameleon
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (useRandom)
|
||||
{
|
||||
List<uint> displayIds = new List<uint>();
|
||||
for (var i = 0; i < formModelData.Choices.Count; ++i)
|
||||
{
|
||||
ChrCustomizationDisplayInfoRecord displayInfo = formModelData.Displays[i];
|
||||
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))
|
||||
displayIds.Add(displayInfo.DisplayID);
|
||||
}
|
||||
}
|
||||
|
||||
if (!displayIds.Empty())
|
||||
return displayIds.SelectRandom();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint formChoice = thisPlayer.GetCustomizationChoice(formModelData.OptionID);
|
||||
if (formChoice != 0)
|
||||
{
|
||||
var choiceIndex = formModelData.Choices.FindIndex(choice =>
|
||||
{
|
||||
return choice.Id == formChoice;
|
||||
});
|
||||
|
||||
if (choiceIndex != -1)
|
||||
{
|
||||
ChrCustomizationDisplayInfoRecord displayInfo = formModelData.Displays[choiceIndex];
|
||||
if (displayInfo != null)
|
||||
return displayInfo.DisplayID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (form)
|
||||
{
|
||||
case ShapeShiftForm.CatForm:
|
||||
{
|
||||
if (GetRace() == Race.NightElf)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 10);
|
||||
|
||||
switch (hairColor)
|
||||
{
|
||||
case 7: // Violet
|
||||
case 8:
|
||||
return 29405;
|
||||
case 3: // Light Blue
|
||||
return 29406;
|
||||
case 0: // Green
|
||||
case 1: // Light Green
|
||||
case 2: // Dark Green
|
||||
return 29407;
|
||||
case 4: // White
|
||||
return 29408;
|
||||
default: // original - Dark Blue
|
||||
return 892;
|
||||
}
|
||||
}
|
||||
else if (GetRace() == Race.Troll)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 12);
|
||||
|
||||
switch (hairColor)
|
||||
{
|
||||
case 0: // Red
|
||||
case 1:
|
||||
return 33668;
|
||||
case 2: // Yellow
|
||||
case 3:
|
||||
return 33667;
|
||||
case 4: // Blue
|
||||
case 5:
|
||||
case 6:
|
||||
return 33666;
|
||||
case 7: // Purple
|
||||
case 10:
|
||||
return 33665;
|
||||
default: // original - white
|
||||
return 33669;
|
||||
}
|
||||
}
|
||||
else if (GetRace() == Race.Worgen)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
skinColor = (byte)RandomHelper.URand(0, 9);
|
||||
|
||||
// Male
|
||||
if (GetGender() == Gender.Male)
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 1: // Brown
|
||||
return 33662;
|
||||
case 2: // Black
|
||||
case 7:
|
||||
return 33661;
|
||||
case 4: // yellow
|
||||
return 33664;
|
||||
case 3: // White
|
||||
case 5:
|
||||
return 33663;
|
||||
default: // original - Gray
|
||||
return 33660;
|
||||
}
|
||||
}
|
||||
// Female
|
||||
else
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 5: // Brown
|
||||
case 6:
|
||||
return 33662;
|
||||
case 7: // Black
|
||||
case 8:
|
||||
return 33661;
|
||||
case 3: // yellow
|
||||
case 4:
|
||||
return 33664;
|
||||
case 2: // White
|
||||
return 33663;
|
||||
default: // original - Gray
|
||||
return 33660;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GetRace() == Race.Tauren)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
skinColor = (byte)RandomHelper.URand(0, 20);
|
||||
|
||||
if (GetGender() == Gender.Male)
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 12: // White
|
||||
case 13:
|
||||
case 14:
|
||||
case 18: // Completly White
|
||||
return 29409;
|
||||
case 9: // Light Brown
|
||||
case 10:
|
||||
case 11:
|
||||
return 29410;
|
||||
case 6: // Brown
|
||||
case 7:
|
||||
case 8:
|
||||
return 29411;
|
||||
case 0: // Dark
|
||||
case 1:
|
||||
case 2:
|
||||
case 3: // Dark Grey
|
||||
case 4:
|
||||
case 5:
|
||||
return 29412;
|
||||
default: // original - Grey
|
||||
return 8571;
|
||||
}
|
||||
}
|
||||
// Female
|
||||
else
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 10: // White
|
||||
return 29409;
|
||||
case 6: // Light Brown
|
||||
case 7:
|
||||
return 29410;
|
||||
case 4: // Brown
|
||||
case 5:
|
||||
return 29411;
|
||||
case 0: // Dark
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return 29412;
|
||||
default: // original - Grey
|
||||
return 8571;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Player.TeamForRace(GetRace()) == Team.Alliance)
|
||||
return 892;
|
||||
else
|
||||
return 8571;
|
||||
}
|
||||
case ShapeShiftForm.BearForm:
|
||||
{
|
||||
if (GetRace() == Race.NightElf)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 8);
|
||||
|
||||
switch (hairColor)
|
||||
{
|
||||
case 0: // Green
|
||||
case 1: // Light Green
|
||||
case 2: // Dark Green
|
||||
return 29413; // 29415?
|
||||
case 6: // Dark Blue
|
||||
return 29414;
|
||||
case 4: // White
|
||||
return 29416;
|
||||
case 3: // Light Blue
|
||||
return 29417;
|
||||
default: // original - Violet
|
||||
return 29415;
|
||||
}
|
||||
}
|
||||
else if (GetRace() == Race.Troll)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 14);
|
||||
|
||||
switch (hairColor)
|
||||
{
|
||||
case 0: // Red
|
||||
case 1:
|
||||
return 33657;
|
||||
case 2: // Yellow
|
||||
case 3:
|
||||
return 33659;
|
||||
case 7: // Purple
|
||||
case 10:
|
||||
return 33656;
|
||||
case 8: // White
|
||||
case 9:
|
||||
case 11:
|
||||
case 12:
|
||||
return 33658;
|
||||
default: // original - Blue
|
||||
return 33655;
|
||||
}
|
||||
}
|
||||
else if (GetRace() == Race.Worgen)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
skinColor = (byte)RandomHelper.URand(0, 8);
|
||||
|
||||
// Male
|
||||
if (GetGender() == Gender.Male)
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 1: // Brown
|
||||
return 33652;
|
||||
case 2: // Black
|
||||
case 7:
|
||||
return 33651;
|
||||
case 4: // Yellow
|
||||
return 33653;
|
||||
case 3: // White
|
||||
case 5:
|
||||
return 33654;
|
||||
default: // original - Gray
|
||||
return 33650;
|
||||
}
|
||||
}
|
||||
// Female
|
||||
else
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 5: // Brown
|
||||
case 6:
|
||||
return 33652;
|
||||
case 7: // Black
|
||||
case 8:
|
||||
return 33651;
|
||||
case 3: // yellow
|
||||
case 4:
|
||||
return 33654;
|
||||
case 2: // White
|
||||
return 33653;
|
||||
default: // original - Gray
|
||||
return 33650;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (GetRace() == Race.Tauren)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
skinColor = (byte)RandomHelper.URand(0, 20);
|
||||
|
||||
if (GetGender() == Gender.Male)
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 0: // Dark (Black)
|
||||
case 1:
|
||||
case 2:
|
||||
return 29418;
|
||||
case 3: // White
|
||||
case 4:
|
||||
case 5:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
return 29419;
|
||||
case 9: // Light Brown/Grey
|
||||
case 10:
|
||||
case 11:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
return 29420;
|
||||
case 18: // Completly White
|
||||
return 29421;
|
||||
default: // original - Brown
|
||||
return 2289;
|
||||
}
|
||||
}
|
||||
// Female
|
||||
else
|
||||
{
|
||||
switch (skinColor)
|
||||
{
|
||||
case 0: // Dark (Black)
|
||||
case 1:
|
||||
return 29418;
|
||||
case 2: // White
|
||||
case 3:
|
||||
return 29419;
|
||||
case 6: // Light Brown/Grey
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
return 29420;
|
||||
case 10: // Completly White
|
||||
return 29421;
|
||||
default: // original - Brown
|
||||
return 2289;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Player.TeamForRace(GetRace()) == Team.Alliance)
|
||||
return 29415;
|
||||
else
|
||||
return 2289;
|
||||
}
|
||||
case ShapeShiftForm.FlightForm:
|
||||
if (Player.TeamForRace(GetRace()) == Team.Alliance)
|
||||
return 20857;
|
||||
return 20872;
|
||||
case ShapeShiftForm.FlightFormEpic:
|
||||
if (HasAura(219062)) // Glyph of the Sentinel
|
||||
{
|
||||
switch (GetRace())
|
||||
{
|
||||
case Race.NightElf: // Blue
|
||||
return 64328;
|
||||
case Race.Tauren: // Brown
|
||||
return 64329;
|
||||
case Race.Worgen: // Purple
|
||||
return 64330;
|
||||
case Race.Troll: // White
|
||||
return 64331;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Player.TeamForRace(GetRace()) == Team.Alliance)
|
||||
return (GetRace() == Race.Worgen ? 37729 : 21243u);
|
||||
if (GetRace() == Race.Troll)
|
||||
return 37730;
|
||||
return 21244;
|
||||
case ShapeShiftForm.MoonkinForm:
|
||||
switch (GetRace())
|
||||
{
|
||||
case Race.NightElf:
|
||||
return 15374;
|
||||
case Race.Tauren:
|
||||
return 15375;
|
||||
case Race.Worgen:
|
||||
return 37173;
|
||||
case Race.Troll:
|
||||
return 37174;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ShapeShiftForm.AquaticForm:
|
||||
if (HasAura(114333)) // Glyph of the Orca
|
||||
return 4591;
|
||||
return 2428;
|
||||
case ShapeShiftForm.TravelForm:
|
||||
{
|
||||
if (HasAura(131113)) // Glyph of the Cheetah
|
||||
return 1043;
|
||||
|
||||
if (HasAura(224122)) // Glyph of the Doe
|
||||
return 70450;
|
||||
|
||||
switch (GetRace())
|
||||
{
|
||||
case Race.NightElf:
|
||||
case Race.Worgen:
|
||||
return 40816;
|
||||
case Race.Troll:
|
||||
case Race.Tauren:
|
||||
return 45339;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ShapeShiftForm.GhostWolf:
|
||||
if (HasAura(58135)) // Glyph of Spectral Wolf
|
||||
return 60247;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint modelid = 0;
|
||||
SpellShapeshiftFormRecord formEntry = CliDB.SpellShapeshiftFormStorage.LookupByKey((uint)form);
|
||||
SpellShapeshiftFormRecord formEntry = CliDB.SpellShapeshiftFormStorage.LookupByKey(form);
|
||||
if (formEntry != null && formEntry.CreatureDisplayID[0] != 0)
|
||||
{
|
||||
// Take the alliance modelid as default
|
||||
if (!IsTypeId(TypeId.Player))
|
||||
if (GetTypeId() != TypeId.Player)
|
||||
return formEntry.CreatureDisplayID[0];
|
||||
else
|
||||
{
|
||||
@@ -2673,11 +2359,12 @@ namespace Game.Entities
|
||||
{
|
||||
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelData)._value.SpellID, channelSpellId);
|
||||
}
|
||||
public uint GetChannelSpellXSpellVisualId() { return ((UnitChannel)m_unitData.ChannelData).SpellXSpellVisualID; }
|
||||
public void SetChannelSpellXSpellVisualId(SpellCastVisual channelVisual)
|
||||
public uint GetChannelSpellXSpellVisualId() { return m_unitData.ChannelData.GetValue().SpellVisual.SpellXSpellVisualID; }
|
||||
public uint GetChannelScriptVisualId() { return m_unitData.ChannelData.GetValue().SpellVisual.ScriptVisualID; }
|
||||
public void SetChannelVisual(SpellCastVisualField channelVisual)
|
||||
{
|
||||
UnitChannel unitChannel = m_unitData.ModifyValue(m_unitData.ChannelData);
|
||||
SetUpdateFieldValue(ref unitChannel.SpellXSpellVisualID, channelVisual.SpellXSpellVisualID);
|
||||
SetUpdateFieldValue(ref unitChannel.SpellVisual, channelVisual);
|
||||
}
|
||||
public void AddChannelObject(ObjectGuid guid) { AddDynamicUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects), guid); }
|
||||
public void SetChannelObject(int slot, ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ChannelObjects, slot), guid); }
|
||||
|
||||
@@ -4589,25 +4589,6 @@ namespace Game
|
||||
itemTemplate.Effects.Add(effectEntry);
|
||||
}
|
||||
|
||||
// Check if item templates for DBC referenced character start outfit are present
|
||||
List<uint> notFoundOutfit = new List<uint>();
|
||||
foreach (var entry in CliDB.CharStartOutfitStorage.Values)
|
||||
{
|
||||
for (int j = 0; j < ItemConst.MaxOutfitItems; ++j)
|
||||
{
|
||||
if (entry.ItemID[j] <= 0)
|
||||
continue;
|
||||
|
||||
uint item_id = (uint)entry.ItemID[j];
|
||||
|
||||
if (GetItemTemplate(item_id) == null)
|
||||
notFoundOutfit.Add(item_id);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var id in notFoundOutfit)
|
||||
Log.outError(LogFilter.Sql, "Item (Entry: {0}) item does not exist but is referenced in `CharStartOutfit.dbc`", id);
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} item templates in {1} ms", sparseCount, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
@@ -5510,28 +5491,42 @@ namespace Game
|
||||
float positionZ = result.Read<float>(6);
|
||||
float orientation = result.Read<float>(7);
|
||||
|
||||
if (currentrace >= (int)Race.Max)
|
||||
if (CliDB.ChrRacesStorage.ContainsKey(currentrace))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Wrong race {0} in `playercreateinfo` table, ignoring.", currentrace);
|
||||
Log.outError(LogFilter.Sql, $"Wrong race {currentrace} in `playercreateinfo` table, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
var rEntry = CliDB.ChrRacesStorage.LookupByKey(currentrace);
|
||||
if (rEntry == null)
|
||||
if (CliDB.ChrClassesStorage.ContainsKey(currentclass))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Wrong race {0} in `playercreateinfo` table, ignoring.", currentrace);
|
||||
Log.outError(LogFilter.Sql, $"Wrong class {currentclass} in `playercreateinfo` table, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentclass >= (int)Class.Max)
|
||||
// accept DB data only for valid position (and non instanceable)
|
||||
if (!GridDefines.IsValidMapCoord(mapId, positionX, positionY, positionZ, orientation))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Wrong class {0} in `playercreateinfo` table, ignoring.", currentclass);
|
||||
Log.outError(LogFilter.Sql, $"Wrong home position for class {currentclass} race {currentrace} pair in `playercreateinfo` table, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CliDB.ChrClassesStorage.LookupByKey(currentclass) == null)
|
||||
if (CliDB.MapStorage.LookupByKey(mapId).Instanceable())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Wrong class {0} in `playercreateinfo` table, ignoring.", currentclass);
|
||||
Log.outError(LogFilter.Sql, $"Home position in instanceable map for class {currentclass} race {currentrace} pair in `playercreateinfo` table, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
ChrModelRecord maleModel = Global.DB2Mgr.GetChrModel((Race)currentrace, Gender.Male);
|
||||
if (maleModel == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Missing male model for race {currentrace}, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
ChrModelRecord femaleModel = Global.DB2Mgr.GetChrModel((Race)currentrace, Gender.Female);
|
||||
if (femaleModel == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Missing female model for race {currentrace}, ignoring.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5543,8 +5538,8 @@ namespace Game
|
||||
pInfo.PositionZ = positionZ;
|
||||
pInfo.Orientation = orientation;
|
||||
|
||||
pInfo.DisplayId_m = rEntry.MaleDisplayId;
|
||||
pInfo.DisplayId_f = rEntry.FemaleDisplayId;
|
||||
pInfo.DisplayId_m = maleModel.DisplayID;
|
||||
pInfo.DisplayId_f = femaleModel.DisplayID;
|
||||
|
||||
_playerInfo[currentrace][currentclass] = pInfo;
|
||||
|
||||
@@ -5556,6 +5551,63 @@ namespace Game
|
||||
time = Time.GetMSTime();
|
||||
// Load playercreate items
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Player Create Items Data...");
|
||||
{
|
||||
MultiMap<uint, ItemTemplate> itemsByCharacterLoadout = new MultiMap<uint, ItemTemplate>();
|
||||
foreach (CharacterLoadoutItemRecord characterLoadoutItem in CliDB.CharacterLoadoutItemStorage.Values)
|
||||
{
|
||||
ItemTemplate itemTemplate = GetItemTemplate(characterLoadoutItem.ItemID);
|
||||
if (itemTemplate != null)
|
||||
itemsByCharacterLoadout.Add(characterLoadoutItem.CharacterLoadoutID, itemTemplate);
|
||||
}
|
||||
|
||||
foreach (CharacterLoadoutRecord characterLoadout in CliDB.CharacterLoadoutStorage.Values)
|
||||
{
|
||||
if (!characterLoadout.IsForNewCharacter())
|
||||
continue;
|
||||
|
||||
var items = itemsByCharacterLoadout.LookupByKey(characterLoadout.Id);
|
||||
if (items.Empty())
|
||||
continue;
|
||||
|
||||
for (uint raceIndex = (int)Race.Human; raceIndex < (int)Race.Max; ++raceIndex)
|
||||
{
|
||||
if (!characterLoadout.RaceMask.HasAnyFlag(raceIndex))
|
||||
continue;
|
||||
|
||||
PlayerInfo playerInfo = _playerInfo[raceIndex][characterLoadout.ChrClassID];
|
||||
if (playerInfo != null)
|
||||
{
|
||||
foreach (ItemTemplate itemTemplate in items)
|
||||
{
|
||||
// BuyCount by default
|
||||
uint count = itemTemplate.GetBuyCount();
|
||||
|
||||
// special amount for food/drink
|
||||
if (itemTemplate.GetClass() == ItemClass.Consumable && (ItemSubClassConsumable)itemTemplate.GetSubClass() == ItemSubClassConsumable.FoodDrink)
|
||||
{
|
||||
if (!itemTemplate.Effects.Empty())
|
||||
{
|
||||
switch ((SpellCategories)itemTemplate.Effects[0].SpellCategoryID)
|
||||
{
|
||||
case SpellCategories.Food: // food
|
||||
count = characterLoadout.ChrClassID == (int)Class.Deathknight ? 10 : 4u;
|
||||
break;
|
||||
case SpellCategories.Drink: // drink
|
||||
count = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (itemTemplate.GetMaxStackSize() < count)
|
||||
count = itemTemplate.GetMaxStackSize();
|
||||
}
|
||||
|
||||
playerInfo.item.Add(new PlayerCreateInfoItem(itemTemplate.GetId(), count));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loading Player Create Items Override Data...");
|
||||
{
|
||||
// 0 1 2 3
|
||||
SQLResult result = DB.World.Query("SELECT race, class, itemid, amount FROM playercreateinfo_item");
|
||||
@@ -5986,38 +6038,20 @@ namespace Game
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} xp for level definition(s) from database in {1} ms", count, Time.GetMSTimeDiffToNow(time));
|
||||
}
|
||||
}
|
||||
void PlayerCreateInfoAddItemHelper(uint race, uint _class, uint itemId, int count)
|
||||
void PlayerCreateInfoAddItemHelper(uint race, uint class_, uint itemId, int count)
|
||||
{
|
||||
if (_playerInfo[race][_class] == null)
|
||||
if (_playerInfo[race][class_] == null)
|
||||
return;
|
||||
|
||||
if (count > 0)
|
||||
_playerInfo[race][_class].item.Add(new PlayerCreateInfoItem(itemId, (uint)count));
|
||||
_playerInfo[race][class_].item.Add(new PlayerCreateInfoItem(itemId, (uint)count));
|
||||
else
|
||||
{
|
||||
if (count < -1)
|
||||
Log.outError(LogFilter.Sql, "Invalid count {0} specified on item {1} be removed from original player create info (use -1)!", count, itemId);
|
||||
|
||||
for (byte gender = 0; gender < (int)Gender.None; ++gender)
|
||||
{
|
||||
CharStartOutfitRecord entry = Global.DB2Mgr.GetCharStartOutfitEntry(race, _class, gender);
|
||||
if (entry != null)
|
||||
{
|
||||
bool found = false;
|
||||
for (var x = 0; x < ItemConst.MaxOutfitItems; ++x)
|
||||
{
|
||||
if (entry.ItemID[x] > 0 && entry.ItemID[x] == itemId)
|
||||
{
|
||||
found = true;
|
||||
entry.ItemID[x] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
Log.outError(LogFilter.Sql, "Item {0} specified to be removed from original create info not found in dbc!", itemId);
|
||||
}
|
||||
}
|
||||
var items = _playerInfo[race][class_].item;
|
||||
items.RemoveAll(item => { return item.item_id == itemId; });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9416,9 +9450,9 @@ namespace Game
|
||||
int responseId = rewardItems.Read<int>(1);
|
||||
uint itemId = rewardItems.Read<uint>(2);
|
||||
StringArray bonusListIDsTok = new StringArray(rewardItems.Read<string>(3), ' ');
|
||||
List<int> bonusListIds = new List<int>();
|
||||
List<uint> bonusListIds = new List<uint>();
|
||||
foreach (string token in bonusListIDsTok)
|
||||
bonusListIds.Add(int.Parse(token));
|
||||
bonusListIds.Add(uint.Parse(token));
|
||||
|
||||
int quantity = rewardItems.Read<int>(4);
|
||||
|
||||
@@ -9448,7 +9482,7 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
response.Reward.ItemChoices.Add(itemId, bonusListIds, quantity);
|
||||
response.Reward.Value.ItemChoices.Add(new PlayerChoiceResponseRewardItem(itemId, bonusListIds, quantity));
|
||||
itemChoiceRewardCount++;
|
||||
|
||||
} while (rewards.NextRow());
|
||||
@@ -9482,7 +9516,7 @@ namespace Game
|
||||
mawPower.RarityColor = mawPowersResult.Read<uint>(4);
|
||||
mawPower.SpellID = mawPowersResult.Read<int>(5);
|
||||
mawPower.MaxStacks = mawPowersResult.Read<int>(6);
|
||||
response.MawPower.Add(mawPower);
|
||||
response.MawPower.Set(mawPower);
|
||||
|
||||
++mawPowersCount;
|
||||
|
||||
@@ -9757,21 +9791,23 @@ namespace Game
|
||||
switch (expansion)
|
||||
{
|
||||
case Expansion.Classic:
|
||||
return 60;
|
||||
return 30;
|
||||
case Expansion.BurningCrusade:
|
||||
return 70;
|
||||
return 30;
|
||||
case Expansion.WrathOfTheLichKing:
|
||||
return 80;
|
||||
return 30;
|
||||
case Expansion.Cataclysm:
|
||||
return 85;
|
||||
return 35;
|
||||
case Expansion.MistsOfPandaria:
|
||||
return 90;
|
||||
return 35;
|
||||
case Expansion.WarlordsOfDraenor:
|
||||
return 100;
|
||||
return 40;
|
||||
case Expansion.Legion:
|
||||
return 110;
|
||||
return 45;
|
||||
case Expansion.BattleForAzeroth:
|
||||
return 120;
|
||||
return 50;
|
||||
case Expansion.ShadowLands:
|
||||
return 60;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2505,7 +2505,7 @@ namespace Game.Guilds
|
||||
m_name = player.GetName();
|
||||
m_level = (byte)player.GetLevel();
|
||||
m_class = player.GetClass();
|
||||
_gender = (Gender)(byte)player.m_playerData.NativeSex;
|
||||
_gender = player.GetNativeSex();
|
||||
m_zoneId = player.GetZoneId();
|
||||
m_accountId = player.GetSession().GetAccountId();
|
||||
m_achievementPoints = player.GetAchievementPoints();
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace Game
|
||||
Global.CalendarMgr.SendCalendarCommandResult(GetPlayer().GetGUID(), CalendarError.EventInvalid);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.CalendarCommunityInviteRequest)]
|
||||
[WorldPacketHandler(ClientOpcodes.CalendarCommunityInvite)]
|
||||
void HandleCalendarCommunityInvite(CalendarCommunityInviteRequest calendarCommunityInvite)
|
||||
{
|
||||
Guild guild = Global.GuildMgr.GetGuildById(GetPlayer().GetGuildId());
|
||||
@@ -423,7 +423,7 @@ namespace Game
|
||||
Global.CalendarMgr.SendCalendarCommandResult(guid, CalendarError.EventInvalid);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.CalendarEventModeratorStatus)]
|
||||
[WorldPacketHandler(ClientOpcodes.CalendarModeratorStatus)]
|
||||
void HandleCalendarModeratorStatus(CalendarModeratorStatusQuery calendarModeratorStatus)
|
||||
{
|
||||
ObjectGuid guid = GetPlayer().GetGUID();
|
||||
|
||||
@@ -28,6 +28,7 @@ using Game.Networking;
|
||||
using Game.Networking.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
@@ -41,57 +42,77 @@ namespace Game
|
||||
DB.Characters.Execute(stmt);
|
||||
|
||||
// get all the data necessary for loading all characters (along with their pets) on the account
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed))
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_ENUM_DECLINED_NAME);
|
||||
else
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_ENUM);
|
||||
EnumCharactersQueryHolder holder = new EnumCharactersQueryHolder();
|
||||
if (!holder.Initialize(GetAccountId(), WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed), false))
|
||||
{
|
||||
HandleCharEnum(holder);
|
||||
return;
|
||||
}
|
||||
|
||||
stmt.AddValue(0, PetSaveMode.AsCurrent);
|
||||
stmt.AddValue(1, GetAccountId());
|
||||
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharEnumCallback));
|
||||
_charEnumCallback = DB.Characters.DelayQueryHolder(holder);
|
||||
}
|
||||
|
||||
void HandleCharEnumCallback(SQLResult result)
|
||||
void HandleCharEnum(EnumCharactersQueryHolder holder)
|
||||
{
|
||||
EnumCharactersResult charResult = new EnumCharactersResult();
|
||||
charResult.Success = true;
|
||||
charResult.IsDeletedCharacters = false;
|
||||
charResult.IsDeletedCharacters = holder.IsDeletedCharacters();
|
||||
charResult.DisabledClassesMask.Set(WorldConfig.GetUIntValue(WorldCfg.CharacterCreatingDisabledClassmask));
|
||||
|
||||
_legitCharacters.Clear();
|
||||
if (!charResult.IsDeletedCharacters)
|
||||
_legitCharacters.Clear();
|
||||
|
||||
MultiMap<ulong, ChrCustomizationChoice> customizations = new MultiMap<ulong, ChrCustomizationChoice>();
|
||||
SQLResult customizationsResult = holder.GetResult(EnumCharacterQueryLoad.Customizations);
|
||||
if (!customizationsResult.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
var customizationsForCharacter = customizations[customizationsResult.Read<ulong>(0)];
|
||||
|
||||
ChrCustomizationChoice choice = new ChrCustomizationChoice();
|
||||
choice.ChrCustomizationOptionID = customizationsResult.Read<uint>(1);
|
||||
choice.ChrCustomizationChoiceID = customizationsResult.Read<uint>(2);
|
||||
customizationsForCharacter.Add(choice);
|
||||
|
||||
} while (customizationsResult.NextRow());
|
||||
}
|
||||
|
||||
SQLResult result = holder.GetResult(EnumCharacterQueryLoad.Characters);
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
EnumCharactersResult.CharacterInfo charInfo = new EnumCharactersResult.CharacterInfo(result.GetFields());
|
||||
|
||||
var customizationsForChar = customizations.LookupByKey(charInfo.Guid.GetCounter());
|
||||
if (!customizationsForChar.Empty())
|
||||
charInfo.Customizations = (Array<ChrCustomizationChoice>)customizationsForChar.ToList();
|
||||
|
||||
Log.outInfo(LogFilter.Network, "Loading Character {0} from account {1}.", charInfo.Guid.ToString(), GetAccountId());
|
||||
|
||||
if (!Player.ValidateAppearance((Race)charInfo.RaceId, charInfo.ClassId, (Gender)charInfo.SexId, charInfo.HairStyle, charInfo.HairColor, charInfo.FaceId, charInfo.FacialHair, charInfo.SkinId, charInfo.CustomDisplay))
|
||||
if (!charResult.IsDeletedCharacters)
|
||||
{
|
||||
Log.outError(LogFilter.Player, "Player {0} has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString());
|
||||
|
||||
// Make sure customization always works properly - send all zeroes instead
|
||||
charInfo.SkinId = 0;
|
||||
charInfo.FaceId = 0;
|
||||
charInfo.HairStyle = 0;
|
||||
charInfo.HairColor = 0;
|
||||
charInfo.FacialHair = 0;
|
||||
|
||||
if (charInfo.Flags2 != CharacterCustomizeFlags.Customize)
|
||||
if (!ValidateAppearance((Race)charInfo.RaceId, charInfo.ClassId, (Gender)charInfo.SexId, charInfo.Customizations))
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ADD_AT_LOGIN_FLAG);
|
||||
stmt.AddValue(0, (ushort)AtLoginFlags.Customize);
|
||||
stmt.AddValue(1, charInfo.Guid.GetCounter());
|
||||
DB.Characters.Execute(stmt);
|
||||
charInfo.Flags2 = CharacterCustomizeFlags.Customize;
|
||||
}
|
||||
}
|
||||
Log.outError(LogFilter.Player, "Player {0} has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString());
|
||||
|
||||
// Do not allow locked characters to login
|
||||
if (!charInfo.Flags.HasAnyFlag(CharacterFlags.CharacterLockedForTransfer | CharacterFlags.LockedByBilling))
|
||||
_legitCharacters.Add(charInfo.Guid);
|
||||
charInfo.Customizations.Clear();
|
||||
|
||||
if (charInfo.Flags2 != CharacterCustomizeFlags.Customize)
|
||||
{
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ADD_AT_LOGIN_FLAG);
|
||||
stmt.AddValue(0, (ushort)AtLoginFlags.Customize);
|
||||
stmt.AddValue(1, charInfo.Guid.GetCounter());
|
||||
DB.Characters.Execute(stmt);
|
||||
charInfo.Flags2 = CharacterCustomizeFlags.Customize;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not allow locked characters to login
|
||||
if (!charInfo.Flags.HasAnyFlag(CharacterFlags.CharacterLockedForTransfer | CharacterFlags.LockedByBilling))
|
||||
_legitCharacters.Add(charInfo.Guid);
|
||||
}
|
||||
|
||||
if (!Global.CharacterCacheStorage.HasCharacterCacheEntry(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
|
||||
Global.CharacterCacheStorage.AddCharacterCacheEntry(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.SexId, charInfo.RaceId, (byte)charInfo.ClassId, charInfo.ExperienceLevel, false);
|
||||
@@ -120,16 +141,14 @@ namespace Game
|
||||
void HandleCharUndeleteEnum(EnumCharacters enumCharacters)
|
||||
{
|
||||
// get all the data necessary for loading all undeleted characters (along with their pets) on the account
|
||||
PreparedStatement stmt;
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed))
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_UNDELETE_ENUM_DECLINED_NAME);
|
||||
else
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_UNDELETE_ENUM);
|
||||
|
||||
stmt.AddValue(0, (uint)PetSaveMode.AsCurrent);
|
||||
stmt.AddValue(1, GetAccountId());
|
||||
|
||||
_queryProcessor.AddCallback(DB.Characters.AsyncQuery(stmt).WithCallback(HandleCharUndeleteEnumCallback));
|
||||
EnumCharactersQueryHolder holder = new EnumCharactersQueryHolder();
|
||||
if (!holder.Initialize(GetAccountId(), WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed), true))
|
||||
{
|
||||
HandleCharEnum(holder);
|
||||
return;
|
||||
}
|
||||
|
||||
_charEnumCallback = DB.Characters.DelayQueryHolder(holder);
|
||||
}
|
||||
|
||||
void HandleCharUndeleteEnumCallback(SQLResult result)
|
||||
@@ -158,6 +177,94 @@ namespace Game
|
||||
SendPacket(charEnum);
|
||||
}
|
||||
|
||||
public bool MeetsChrCustomizationReq(ChrCustomizationReqRecord req, Class playerClass, bool checkRequiredDependentChoices, List<ChrCustomizationChoice> selectedChoices)
|
||||
{
|
||||
if (!req.GetFlags().HasFlag(ChrCustomizationReqFlag.HasRequirements))
|
||||
return true;
|
||||
|
||||
if (req.ClassMask != 0 && (req.ClassMask & (1 << ((int)playerClass - 1))) == 0)
|
||||
return false;
|
||||
|
||||
if (req.AchievementID != 0 /*&& !HasAchieved(req->AchievementID)*/)
|
||||
return false;
|
||||
|
||||
if (req.ItemModifiedAppearanceID != 0 && !GetCollectionMgr().HasItemAppearance(req.ItemModifiedAppearanceID).PermAppearance)
|
||||
return false;
|
||||
|
||||
if (checkRequiredDependentChoices)
|
||||
{
|
||||
var requiredChoices = Global.DB2Mgr.GetRequiredCustomizationChoices(req.Id);
|
||||
if (!requiredChoices.Empty())
|
||||
{
|
||||
foreach (var key in requiredChoices.Keys)
|
||||
{
|
||||
bool hasRequiredChoiceForOption = false;
|
||||
foreach (uint requiredChoice in requiredChoices[key])
|
||||
{
|
||||
if (selectedChoices.Any(choice => choice.ChrCustomizationChoiceID == requiredChoice))
|
||||
{
|
||||
hasRequiredChoiceForOption = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRequiredChoiceForOption)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool ValidateAppearance(Race race, Class playerClass, Gender gender, List<ChrCustomizationChoice> customizations)
|
||||
{
|
||||
var options = Global.DB2Mgr.GetCustomiztionOptions(race, gender);
|
||||
if (options.Empty())
|
||||
return false;
|
||||
|
||||
uint previousOption = 0;
|
||||
|
||||
foreach (var playerChoice in customizations)
|
||||
{
|
||||
// check uniqueness of options
|
||||
if (playerChoice.ChrCustomizationOptionID == previousOption)
|
||||
return false;
|
||||
|
||||
previousOption = playerChoice.ChrCustomizationOptionID;
|
||||
|
||||
// check if we can use this option
|
||||
var customizationOptionData = options.Find(option => { return option.Id == playerChoice.ChrCustomizationOptionID; });
|
||||
|
||||
// option not found for race/gender combination
|
||||
if (customizationOptionData == null)
|
||||
return false;
|
||||
|
||||
ChrCustomizationReqRecord req = CliDB.ChrCustomizationReqStorage.LookupByKey(customizationOptionData.ChrCustomizationReqID);
|
||||
if (req != null)
|
||||
if (!MeetsChrCustomizationReq(req, playerClass, false, customizations))
|
||||
return false;
|
||||
|
||||
var choicesForOption = Global.DB2Mgr.GetCustomiztionChoices(playerChoice.ChrCustomizationOptionID);
|
||||
if (choicesForOption.Empty())
|
||||
return false;
|
||||
|
||||
var customizationChoiceData = choicesForOption.Find(choice => { return choice.Id == playerChoice.ChrCustomizationChoiceID; });
|
||||
|
||||
// choice not found for option
|
||||
if (customizationChoiceData == null)
|
||||
return false;
|
||||
|
||||
ChrCustomizationReqRecord reqEntry = CliDB.ChrCustomizationReqStorage.LookupByKey(customizationChoiceData.ChrCustomizationReqID);
|
||||
if (reqEntry != null)
|
||||
if (!MeetsChrCustomizationReq(reqEntry, playerClass, true, customizations))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.CreateCharacter, Status = SessionStatus.Authed)]
|
||||
void HandleCharCreate(CreateCharacter charCreate)
|
||||
{
|
||||
@@ -332,7 +439,7 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int demonHunterReqLevel = WorldConfig.GetIntValue(WorldCfg.CharacterCreatingMinLevelForDemonHunter);
|
||||
bool hasDemonHunterReqLevel = demonHunterReqLevel == 0;
|
||||
bool allowTwoSideAccounts = !Global.WorldMgr.IsPvPRealm() || HasPermission(RBACPermissions.TwoSideCharacterCreation);
|
||||
@@ -386,19 +493,6 @@ namespace Game
|
||||
|
||||
if (checkDemonHunterReqs)
|
||||
{
|
||||
byte acc_class = result1.Read<byte>(2);
|
||||
if (acc_class == (byte)Class.DemonHunter)
|
||||
{
|
||||
if (freeDemonHunterSlots > 0)
|
||||
--freeDemonHunterSlots;
|
||||
|
||||
if (freeDemonHunterSlots == 0)
|
||||
{
|
||||
SendCharCreate(ResponseCodes.CharCreateFailed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasDemonHunterReqLevel)
|
||||
{
|
||||
byte acc_level = result1.Read<byte>(0);
|
||||
@@ -457,7 +551,7 @@ namespace Game
|
||||
{
|
||||
Log.outInfo(LogFilter.Player, "Account: {0} (IP: {1}) Create Character: {2} {3}", GetAccountId(), GetRemoteAddress(), createInfo.Name, newChar.GetGUID().ToString());
|
||||
Global.ScriptMgr.OnPlayerCreate(newChar);
|
||||
Global.CharacterCacheStorage.AddCharacterCacheEntry(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.m_playerData.NativeSex, (byte)newChar.GetRace(), (byte)newChar.GetClass(), (byte)newChar.GetLevel(), false);
|
||||
Global.CharacterCacheStorage.AddCharacterCacheEntry(newChar.GetGUID(), GetAccountId(), newChar.GetName(), (byte)newChar.GetNativeSex(), (byte)newChar.GetRace(), (byte)newChar.GetClass(), (byte)newChar.GetLevel(), false);
|
||||
|
||||
SendCharCreate(ResponseCodes.CharCreateSuccess, newChar.GetGUID());
|
||||
}
|
||||
@@ -474,7 +568,7 @@ namespace Game
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHAR_CREATE_INFO);
|
||||
stmt.AddValue(0, GetAccountId());
|
||||
stmt.AddValue(1, (skipCinematics == 1 || createInfo.ClassId == Class.DemonHunter) ? 12 : 1);
|
||||
stmt.AddValue(1, (skipCinematics == 1 || createInfo.ClassId == Class.DemonHunter) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm)
|
||||
queryCallback.WithCallback(finalizeCharacterCreation).SetNextQuery(DB.Characters.AsyncQuery(stmt));
|
||||
}));
|
||||
}
|
||||
@@ -1227,37 +1321,7 @@ namespace Game
|
||||
[WorldPacketHandler(ClientOpcodes.AlterAppearance)]
|
||||
void HandleAlterAppearance(AlterApperance packet)
|
||||
{
|
||||
BarberShopStyleRecord bs_hair = CliDB.BarberShopStyleStorage.LookupByKey(packet.NewHairStyle);
|
||||
if (bs_hair == null || bs_hair.Type != 0 || bs_hair.Race != (byte)GetPlayer().GetRace() || bs_hair.Sex != GetPlayer().m_playerData.NativeSex)
|
||||
return;
|
||||
|
||||
BarberShopStyleRecord bs_facialHair = CliDB.BarberShopStyleStorage.LookupByKey(packet.NewFacialHair);
|
||||
if (bs_facialHair == null || bs_facialHair.Type != 2 || bs_facialHair.Race != (byte)GetPlayer().GetRace() || bs_facialHair.Sex != GetPlayer().m_playerData.NativeSex)
|
||||
return;
|
||||
|
||||
BarberShopStyleRecord bs_skinColor = CliDB.BarberShopStyleStorage.LookupByKey(packet.NewSkinColor);
|
||||
if (bs_skinColor != null && (bs_skinColor.Type != 3 || bs_skinColor.Race != (byte)GetPlayer().GetRace() || bs_skinColor.Sex != GetPlayer().m_playerData.NativeSex))
|
||||
return;
|
||||
|
||||
BarberShopStyleRecord bs_face = CliDB.BarberShopStyleStorage.LookupByKey(packet.NewFace);
|
||||
if (bs_face != null && (bs_face.Type != 4 || bs_face.Race != (byte)GetPlayer().GetRace() || bs_face.Sex != GetPlayer().m_playerData.NativeSex))
|
||||
return;
|
||||
|
||||
Array<BarberShopStyleRecord> customDisplayEntries = new Array<BarberShopStyleRecord>(PlayerConst.CustomDisplaySize);
|
||||
Array<byte> customDisplay = new Array<byte>(PlayerConst.CustomDisplaySize);
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
{
|
||||
BarberShopStyleRecord bs_customDisplay = CliDB.BarberShopStyleStorage.LookupByKey(packet.NewCustomDisplay[i]);
|
||||
if (bs_customDisplay != null && (bs_customDisplay.Type != 5 + i || bs_customDisplay.Race != (byte)_player.GetRace() || bs_customDisplay.Sex != _player.m_playerData.NativeSex))
|
||||
return;
|
||||
|
||||
customDisplayEntries[i] = bs_customDisplay;
|
||||
customDisplay[i] = (byte)(bs_customDisplay != null ? bs_customDisplay.Data : 0);
|
||||
}
|
||||
|
||||
if (!Player.ValidateAppearance(GetPlayer().GetRace(), GetPlayer().GetClass(), (Gender)(byte)GetPlayer().m_playerData.NativeSex,
|
||||
bs_hair.Data, (byte)packet.NewHairColor, bs_face != null ? bs_face.Data : GetPlayer().m_playerData.FaceID,
|
||||
bs_facialHair.Data, bs_skinColor != null ? bs_skinColor.Data : GetPlayer().m_playerData.SkinID, customDisplay))
|
||||
if (!ValidateAppearance(_player.GetRace(), _player.GetClass(), (Gender)packet.NewSex, packet.Customizations))
|
||||
return;
|
||||
|
||||
GameObject go = GetPlayer().FindNearestGameObjectOfType(GameObjectTypes.BarberChair, 5.0f);
|
||||
@@ -1273,8 +1337,8 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
|
||||
uint cost = GetPlayer().GetBarberShopCost(bs_hair, packet.NewHairColor, bs_facialHair, bs_skinColor, bs_face, customDisplayEntries);
|
||||
if (!GetPlayer().HasEnoughMoney((ulong)cost))
|
||||
long cost = GetPlayer().GetBarberShopCost(packet.Customizations);
|
||||
if (!GetPlayer().HasEnoughMoney(cost))
|
||||
{
|
||||
SendPacket(new BarberShopResult(BarberShopResult.ResultEnum.NoMoney));
|
||||
return;
|
||||
@@ -1283,22 +1347,16 @@ namespace Game
|
||||
SendPacket(new BarberShopResult(BarberShopResult.ResultEnum.Success));
|
||||
|
||||
_player.ModifyMoney(-cost);
|
||||
_player.UpdateCriteria(CriteriaTypes.GoldSpentAtBarber, cost);
|
||||
_player.UpdateCriteria(CriteriaTypes.GoldSpentAtBarber, (ulong)cost);
|
||||
|
||||
_player.SetHairStyleId(bs_hair.Data);
|
||||
_player.SetHairColorId((byte)packet.NewHairColor);
|
||||
_player.SetFacialHairStyleId(bs_facialHair.Data);
|
||||
if (bs_skinColor != null)
|
||||
GetPlayer().SetSkinId(bs_skinColor.Data);
|
||||
if (bs_face != null)
|
||||
_player.SetFaceId(bs_face.Data);
|
||||
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
_player.SetCustomDisplayOption(i, customDisplay[i]);
|
||||
_player.SetNativeSex((Gender)packet.NewSex);
|
||||
_player.SetCustomizations(packet.Customizations);
|
||||
|
||||
_player.UpdateCriteria(CriteriaTypes.VisitBarberShop, 1);
|
||||
|
||||
_player.SetStandState(UnitStandStateType.Stand);
|
||||
|
||||
Global.CharacterCacheStorage.UpdateCharacterGender(_player.GetGUID(), packet.NewSex);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.CharCustomize, Status = SessionStatus.Authed)]
|
||||
@@ -1327,13 +1385,12 @@ namespace Game
|
||||
}
|
||||
|
||||
string oldName = result.Read<string>(0);
|
||||
byte plrRace = result.Read<byte>(1);
|
||||
byte plrClass = result.Read<byte>(2);
|
||||
byte plrGender = result.Read<byte>(3);
|
||||
Race plrRace = (Race)result.Read<byte>(1);
|
||||
Class plrClass = (Class)result.Read<byte>(2);
|
||||
Gender plrGender = (Gender)result.Read<byte>(3);
|
||||
AtLoginFlags atLoginFlags = (AtLoginFlags)result.Read<ushort>(4);
|
||||
|
||||
if (!Player.ValidateAppearance((Race)plrRace, (Class)plrClass, (Gender)plrGender, customizeInfo.HairStyleID, customizeInfo.HairColorID, customizeInfo.FaceID,
|
||||
customizeInfo.FacialHairStyleID, customizeInfo.SkinID, customizeInfo.CustomDisplay))
|
||||
if (!ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo.Customizations))
|
||||
{
|
||||
SendCharCustomize(ResponseCodes.CharCreateError, customizeInfo);
|
||||
return;
|
||||
@@ -1392,22 +1449,7 @@ namespace Game
|
||||
ulong lowGuid = customizeInfo.CharGUID.GetCounter();
|
||||
|
||||
// Customize
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_GENDER_AND_APPEARANCE);
|
||||
|
||||
stmt.AddValue(0, customizeInfo.SexID);
|
||||
stmt.AddValue(1, customizeInfo.SkinID);
|
||||
stmt.AddValue(2, customizeInfo.FaceID);
|
||||
stmt.AddValue(3, customizeInfo.HairStyleID);
|
||||
stmt.AddValue(4, customizeInfo.HairColorID);
|
||||
stmt.AddValue(5, customizeInfo.FacialHairStyleID);
|
||||
stmt.AddValue(6, customizeInfo.CustomDisplay[0]);
|
||||
stmt.AddValue(7, customizeInfo.CustomDisplay[1]);
|
||||
stmt.AddValue(8, customizeInfo.CustomDisplay[2]);
|
||||
stmt.AddValue(9, lowGuid);
|
||||
|
||||
trans.Append(stmt);
|
||||
}
|
||||
Player.SaveCustomizations(trans, lowGuid, customizeInfo.Customizations);
|
||||
|
||||
// Name Change and update atLogin flags
|
||||
{
|
||||
@@ -1505,7 +1547,7 @@ namespace Game
|
||||
if (illusion.ItemVisual == 0 || !illusion.Flags.HasAnyFlag(EnchantmentSlotMask.Collectable))
|
||||
return false;
|
||||
|
||||
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogPlayerConditionID);
|
||||
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogUseConditionID);
|
||||
if (condition != null)
|
||||
if (!ConditionManager.IsPlayerMeetingCondition(_player, condition))
|
||||
return false;
|
||||
@@ -1735,21 +1777,7 @@ namespace Game
|
||||
}
|
||||
|
||||
// Customize
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_GENDER_AND_APPEARANCE);
|
||||
stmt.AddValue(0, factionChangeInfo.SexID);
|
||||
stmt.AddValue(1, factionChangeInfo.SkinID);
|
||||
stmt.AddValue(2, factionChangeInfo.FaceID);
|
||||
stmt.AddValue(3, factionChangeInfo.HairStyleID);
|
||||
stmt.AddValue(4, factionChangeInfo.HairColorID);
|
||||
stmt.AddValue(5, factionChangeInfo.FacialHairStyleID);
|
||||
stmt.AddValue(6, factionChangeInfo.CustomDisplay[0]);
|
||||
stmt.AddValue(7, factionChangeInfo.CustomDisplay[1]);
|
||||
stmt.AddValue(8, factionChangeInfo.CustomDisplay[2]);
|
||||
stmt.AddValue(9, lowGuid);
|
||||
|
||||
trans.Append(stmt);
|
||||
}
|
||||
Player.SaveCustomizations(trans, lowGuid, factionChangeInfo.Customizations);
|
||||
|
||||
// Race Change
|
||||
{
|
||||
@@ -2511,6 +2539,10 @@ namespace Game
|
||||
stmt.AddValue(0, lowGuid);
|
||||
SetQuery(PlayerLoginQueryLoad.From, stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_CUSTOMIZATIONS);
|
||||
stmt.AddValue(0, lowGuid);
|
||||
SetQuery(PlayerLoginQueryLoad.Customizations, stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_GROUP_MEMBER);
|
||||
stmt.AddValue(0, lowGuid);
|
||||
SetQuery(PlayerLoginQueryLoad.Group, stmt);
|
||||
@@ -2736,10 +2768,41 @@ namespace Game
|
||||
ObjectGuid m_guid;
|
||||
}
|
||||
|
||||
class EnumCharactersQueryHolder : SQLQueryHolder<EnumCharacterQueryLoad>
|
||||
{
|
||||
public bool Initialize(uint accountId, bool withDeclinedNames, bool isDeletedCharacters)
|
||||
{
|
||||
_isDeletedCharacters = isDeletedCharacters;
|
||||
|
||||
CharStatements[][] statements =
|
||||
{
|
||||
new [] { CharStatements.SEL_ENUM, CharStatements.SEL_ENUM_DECLINED_NAME, CharStatements.SEL_ENUM_CUSTOMIZATIONS },
|
||||
new [] { CharStatements.SEL_UNDELETE_ENUM, CharStatements.SEL_UNDELETE_ENUM_DECLINED_NAME, CharStatements.SEL_UNDELETE_ENUM_CUSTOMIZATIONS }
|
||||
};
|
||||
|
||||
bool result = true;
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(statements[isDeletedCharacters ? 1 : 0][withDeclinedNames ? 1 : 0]);
|
||||
stmt.AddValue(0, (byte)PetSaveMode.AsCurrent);
|
||||
stmt.AddValue(1, accountId);
|
||||
SetQuery(EnumCharacterQueryLoad.Characters, stmt);
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(statements[isDeletedCharacters ? 1 : 0][2]);
|
||||
stmt.AddValue(0, accountId);
|
||||
SetQuery(EnumCharacterQueryLoad.Customizations, stmt);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IsDeletedCharacters() { return _isDeletedCharacters; }
|
||||
|
||||
bool _isDeletedCharacters = false;
|
||||
}
|
||||
|
||||
// used at player loading query list preparing, and later result selection
|
||||
public enum PlayerLoginQueryLoad
|
||||
{
|
||||
From,
|
||||
Customizations,
|
||||
Group,
|
||||
BoundInstances,
|
||||
Auras,
|
||||
@@ -2795,4 +2858,10 @@ namespace Game
|
||||
GarrisonFollowerAbilities,
|
||||
Max
|
||||
}
|
||||
|
||||
enum EnumCharacterQueryLoad
|
||||
{
|
||||
Characters,
|
||||
Customizations
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,6 +451,7 @@ namespace Game
|
||||
}
|
||||
|
||||
_player.UpdateCriteria(CriteriaTypes.MoneyFromVendors, money);
|
||||
_player.UpdateCriteria(CriteriaTypes.SoldItemToVendor, 1);
|
||||
|
||||
if (packet.Amount < pItem.GetCount()) // need split items
|
||||
{
|
||||
|
||||
@@ -144,7 +144,8 @@ namespace Game
|
||||
{
|
||||
// Get Random dungeons that can be done at a certain level and expansion
|
||||
uint level = GetPlayer().GetLevel();
|
||||
List<uint> randomDungeons = Global.LFGMgr.GetRandomAndSeasonalDungeons(level, (uint)GetExpansion());
|
||||
uint contentTuningReplacementConditionMask = GetPlayer().m_playerData.CtrOptions.GetValue().ContentTuningConditionMask;
|
||||
var randomDungeons = Global.LFGMgr.GetRandomAndSeasonalDungeons(level, (uint)GetExpansion(), contentTuningReplacementConditionMask);
|
||||
|
||||
LfgPlayerInfo lfgPlayerInfo = new LfgPlayerInfo();
|
||||
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace Game
|
||||
ItemTemplate rewardProto = Global.ObjectMgr.GetItemTemplate(packet.Choice.Item.ItemID);
|
||||
if (rewardProto == null)
|
||||
{
|
||||
Log.outError(LogFilter.Network, "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player {0} ({1}) tried to get invalid reward item (Item Entry: {2}) for quest {3} (possible packet-hacking detected)", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.ItemChoiceID, packet.QuestID);
|
||||
Log.outError(LogFilter.Network, "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player {0} ({1}) tried to get invalid reward item (Item Entry: {2}) for quest {3} (possible packet-hacking detected)", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.Choice.Item.ItemID, packet.QuestID);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace Game
|
||||
|
||||
if (!itemValid)
|
||||
{
|
||||
Log.outError(LogFilter.Network, "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player {0} ({1}) tried to get reward item (Item Entry: {2}) wich is not a reward for quest {3} (possible packet-hacking detected)", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.ItemChoiceID, packet.QuestID);
|
||||
Log.outError(LogFilter.Network, "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player {0} ({1}) tried to get reward item (Item Entry: {2}) wich is not a reward for quest {3} (possible packet-hacking detected)", GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.Choice.Item.ItemID, packet.QuestID);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -529,10 +529,10 @@ namespace Game
|
||||
mirrorImageComponentedData.Gender = (byte)creator.GetGender();
|
||||
mirrorImageComponentedData.ClassID = (byte)creator.GetClass();
|
||||
|
||||
Guild guild = player.GetGuild();
|
||||
|
||||
foreach (var customization in player.m_playerData.Customizations)
|
||||
mirrorImageComponentedData.Customizations.Add(new ChrCustomizationChoice(customization.ChrCustomizationOptionID, customization.ChrCustomizationChoiceID));
|
||||
|
||||
Guild guild = player.GetGuild();
|
||||
mirrorImageComponentedData.GuildGUID = (guild ? guild.GetGUID() : ObjectGuid.Empty);
|
||||
|
||||
byte[] itemSlots =
|
||||
|
||||
@@ -149,12 +149,12 @@ namespace Game
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogPlayerConditionID);
|
||||
PlayerConditionRecord condition = CliDB.PlayerConditionStorage.LookupByKey(illusion.TransmogUseConditionID);
|
||||
if (condition != null)
|
||||
{
|
||||
if (!ConditionManager.IsPlayerMeetingCondition(player, condition))
|
||||
{
|
||||
Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not collected enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID);
|
||||
Log.outDebug(LogFilter.Network, "WORLD: HandleTransmogrifyItems - {0}, Name: {1} tried to transmogrify illusion using not allowed enchant ({2}).", player.GetGUID().ToString(), player.GetName(), transmogItem.SpellItemEnchantmentID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-18
@@ -3290,9 +3290,20 @@ namespace Game.Maps
|
||||
|
||||
public void LoadCorpseData()
|
||||
{
|
||||
MultiMap<ulong, uint> phases = new MultiMap<ulong, uint>();
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CORPSES);
|
||||
stmt.AddValue(0, GetId());
|
||||
stmt.AddValue(1, GetInstanceId());
|
||||
|
||||
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CORPSE_PHASES);
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?
|
||||
SQLResult result = DB.Characters.Query(stmt);
|
||||
if (result.IsEmpty())
|
||||
return;
|
||||
|
||||
MultiMap<ulong, uint> phases = new MultiMap<ulong, uint>();
|
||||
MultiMap<ulong, ChrCustomizationChoice> customizations = new MultiMap<ulong, ChrCustomizationChoice>();
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CORPSE_PHASES);
|
||||
stmt.AddValue(0, GetId());
|
||||
stmt.AddValue(1, GetInstanceId());
|
||||
|
||||
@@ -3311,15 +3322,22 @@ namespace Game.Maps
|
||||
} while (phaseResult.NextRow());
|
||||
}
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CORPSES);
|
||||
stmt.AddValue(0, GetId());
|
||||
stmt.AddValue(1, GetInstanceId());
|
||||
// 0 1 2
|
||||
// SELECT cc.ownerGuid, cc.chrCustomizationOptionID, cc.chrCustomizationChoiceID FROM corpse_customizations cc LEFT JOIN corpse c ON cc.ownerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ?
|
||||
SQLResult customizationResult = DB.Characters.Query(stmt);
|
||||
if (!customizationResult.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
ulong guid = customizationResult.Read<ulong>(0);
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?
|
||||
SQLResult result = DB.Characters.Query(stmt);
|
||||
if (result.IsEmpty())
|
||||
return;
|
||||
ChrCustomizationChoice choice = new ChrCustomizationChoice();
|
||||
choice.ChrCustomizationOptionID = customizationResult.Read<uint>(1);
|
||||
choice.ChrCustomizationChoiceID = customizationResult.Read<uint>(2);
|
||||
customizations.Add(guid, choice);
|
||||
|
||||
} while (customizationResult.NextRow());
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
@@ -3338,6 +3356,8 @@ namespace Game.Maps
|
||||
foreach (var phaseId in phases[guid])
|
||||
PhasingHandler.AddPhase(corpse, phaseId, false);
|
||||
|
||||
corpse.SetCustomizations(customizations[guid]);
|
||||
|
||||
AddCorpse(corpse);
|
||||
} while (result.NextRow());
|
||||
}
|
||||
@@ -3414,19 +3434,12 @@ namespace Game.Maps
|
||||
bones.SetDisplayId(corpse.m_corpseData.DisplayID);
|
||||
bones.SetRace((Race)(byte)corpse.m_corpseData.RaceID);
|
||||
bones.SetSex((Gender)(byte)corpse.m_corpseData.Sex);
|
||||
bones.SetSkin(corpse.m_corpseData.SkinID);
|
||||
bones.SetFace(corpse.m_corpseData.FaceID);
|
||||
bones.SetHairStyle(corpse.m_corpseData.HairStyleID);
|
||||
bones.SetHairColor(corpse.m_corpseData.HairColorID);
|
||||
bones.SetFacialHairStyle(corpse.m_corpseData.FacialHairStyleID);
|
||||
bones.SetCustomizations(corpse.m_corpseData.Customizations);
|
||||
bones.SetFlags((CorpseFlags)(corpse.m_corpseData.Flags | (uint)CorpseFlags.Bones));
|
||||
bones.SetFactionTemplate(corpse.m_corpseData.FactionTemplate);
|
||||
for (int i = 0; i < EquipmentSlot.End; ++i)
|
||||
bones.SetItem((uint)i, corpse.m_corpseData.Items[i]);
|
||||
|
||||
for (int i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
bones.SetCustomDisplayOption((uint)i, corpse.m_corpseData.CustomDisplayOption[i]);
|
||||
|
||||
bones.SetCellCoord(corpse.GetCellCoord());
|
||||
bones.Relocate(corpse.GetPositionX(), corpse.GetPositionY(), corpse.GetPositionZ(), corpse.GetOrientation());
|
||||
|
||||
|
||||
@@ -285,8 +285,8 @@ namespace Game.Movement
|
||||
public void SetAnimation(AnimType anim)
|
||||
{
|
||||
args.time_perc = 0.0f;
|
||||
args.animTier.emplace();
|
||||
args.animTier.AnimTier = anim;
|
||||
args.animTier.HasValue = true;
|
||||
args.animTier.Value.AnimTier = (byte)anim;
|
||||
args.flags.EnableAnimation();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,41 +80,22 @@ namespace Game.Networking.Packets
|
||||
{
|
||||
public CharacterInfo(SQLFields fields)
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.skin, characters.face, characters.hairStyle, "
|
||||
// 8 9 10 11 12 13
|
||||
// "characters.hairColor, characters.facialStyle, characters.customDisplay1, characters.customDisplay2, characters.customDisplay3, characters.level, "
|
||||
// 14 15 16 17 18
|
||||
// "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, "
|
||||
// 19 20 21 22 23 24 25
|
||||
// "guild_member.guildid, characters.playerFlags, characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, "
|
||||
// 26 27 28 29 30 31
|
||||
// "character_banned.guid, characters.slot, characters.logout_time, characters.activeTalentGroup, characters.lastLoginBuild, character_declinedname.genitive"
|
||||
|
||||
Guid = ObjectGuid.Create(HighGuid.Player, fields.Read<ulong>(0));
|
||||
Name = fields.Read<string>(1);
|
||||
RaceId = fields.Read<byte>(2);
|
||||
ClassId = (Class)fields.Read<byte>(3);
|
||||
SexId = fields.Read<byte>(4);
|
||||
SkinId = fields.Read<byte>(5);
|
||||
FaceId = fields.Read<byte>(6);
|
||||
HairStyle = fields.Read<byte>(7);
|
||||
HairColor = fields.Read<byte>(8);
|
||||
FacialHair = fields.Read<byte>(9);
|
||||
CustomDisplay[0] = fields.Read<byte>(10);
|
||||
CustomDisplay[1] = fields.Read<byte>(11);
|
||||
CustomDisplay[2] = fields.Read<byte>(12);
|
||||
ExperienceLevel = fields.Read<byte>(13);
|
||||
ZoneId = fields.Read<uint>(14);
|
||||
MapId = fields.Read<uint>(15);
|
||||
PreloadPos = new Vector3(fields.Read<float>(16), fields.Read<float>(17), fields.Read<float>(18));
|
||||
ExperienceLevel = fields.Read<byte>(5);
|
||||
ZoneId = fields.Read<uint>(6);
|
||||
MapId = fields.Read<uint>(7);
|
||||
PreloadPos = new Vector3(fields.Read<float>(8), fields.Read<float>(9), fields.Read<float>(10));
|
||||
|
||||
ulong guildId = fields.Read<ulong>(19);
|
||||
ulong guildId = fields.Read<ulong>(11);
|
||||
if (guildId != 0)
|
||||
GuildGuid = ObjectGuid.Create(HighGuid.Guild, guildId);
|
||||
|
||||
PlayerFlags playerFlags = (PlayerFlags)fields.Read<uint>(20);
|
||||
AtLoginFlags atLoginFlags = (AtLoginFlags)fields.Read<ushort>(21);
|
||||
PlayerFlags playerFlags = (PlayerFlags)fields.Read<uint>(12);
|
||||
AtLoginFlags atLoginFlags = (AtLoginFlags)fields.Read<ushort>(13);
|
||||
|
||||
if (atLoginFlags.HasAnyFlag(AtLoginFlags.Resurrect))
|
||||
playerFlags &= ~PlayerFlags.Ghost;
|
||||
@@ -125,10 +106,10 @@ namespace Game.Networking.Packets
|
||||
if (atLoginFlags.HasAnyFlag(AtLoginFlags.Rename))
|
||||
Flags |= CharacterFlags.Rename;
|
||||
|
||||
if (fields.Read<uint>(26) != 0)
|
||||
if (fields.Read<uint>(18) != 0)
|
||||
Flags |= CharacterFlags.LockedByBilling;
|
||||
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed) && !string.IsNullOrEmpty(fields.Read<string>(31)))
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.DeclinedNamesUsed) && !string.IsNullOrEmpty(fields.Read<string>(23)))
|
||||
Flags |= CharacterFlags.Declined;
|
||||
|
||||
if (atLoginFlags.HasAnyFlag(AtLoginFlags.Customize))
|
||||
@@ -145,11 +126,11 @@ namespace Game.Networking.Packets
|
||||
// show pet at selection character in character list only for non-ghost character
|
||||
if (!playerFlags.HasAnyFlag(PlayerFlags.Ghost) && (ClassId == Class.Warlock || ClassId == Class.Hunter || ClassId == Class.Deathknight))
|
||||
{
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(fields.Read<uint>(22));
|
||||
CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(fields.Read<uint>(14));
|
||||
if (creatureInfo != null)
|
||||
{
|
||||
PetCreatureDisplayId = fields.Read<uint>(23);
|
||||
PetExperienceLevel = fields.Read<ushort>(24);
|
||||
PetCreatureDisplayId = fields.Read<uint>(15);
|
||||
PetExperienceLevel = fields.Read<ushort>(16);
|
||||
PetCreatureFamilyId = (uint)creatureInfo.Family;
|
||||
}
|
||||
}
|
||||
@@ -158,15 +139,15 @@ namespace Game.Networking.Packets
|
||||
ProfessionIds[0] = 0;
|
||||
ProfessionIds[1] = 0;
|
||||
|
||||
StringArguments equipment = new StringArguments(fields.Read<string>(25));
|
||||
ListPosition = fields.Read<byte>(27);
|
||||
LastPlayedTime = fields.Read<uint>(28);
|
||||
StringArguments equipment = new StringArguments(fields.Read<string>(17));
|
||||
ListPosition = fields.Read<byte>(19);
|
||||
LastPlayedTime = fields.Read<uint>(20);
|
||||
|
||||
var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read<byte>(29));
|
||||
var spec = Global.DB2Mgr.GetChrSpecializationByIndex(ClassId, fields.Read<byte>(21));
|
||||
if (spec != null)
|
||||
SpecID = (ushort)spec.Id;
|
||||
|
||||
LastLoginVersion = fields.Read<uint>(30);
|
||||
LastLoginVersion = fields.Read<uint>(22);
|
||||
|
||||
for (byte slot = 0; slot < InventorySlots.BagEnd; ++slot)
|
||||
{
|
||||
@@ -214,7 +195,10 @@ namespace Game.Networking.Packets
|
||||
data.WriteUInt32(OverrideSelectScreenFileDataID);
|
||||
|
||||
foreach (ChrCustomizationChoice customization in Customizations)
|
||||
customization.Write(data);
|
||||
{
|
||||
data.WriteUInt32(customization.ChrCustomizationOptionID);
|
||||
data.WriteUInt32(customization.ChrCustomizationChoiceID);
|
||||
}
|
||||
|
||||
data.WriteBits(Name.GetByteCount(), 6);
|
||||
data.WriteBit(FirstLogin);
|
||||
@@ -340,7 +324,7 @@ namespace Game.Networking.Packets
|
||||
public uint SequenceIndex;
|
||||
public ResponseCodes Result;
|
||||
|
||||
public CheckCharacterNameAvailabilityResult(uint sequenceIndex, ResponseCodes result) : base(ServerOpcodes.SMSG_CHECK_CHARACTER_NAME_AVAILABILITY_RESULT)
|
||||
public CheckCharacterNameAvailabilityResult(uint sequenceIndex, ResponseCodes result) : base(ServerOpcodes.CheckCharacterNameAvailabilityResult)
|
||||
{
|
||||
SequenceIndex = sequenceIndex;
|
||||
Result = result;
|
||||
@@ -375,7 +359,15 @@ namespace Game.Networking.Packets
|
||||
CreateInfo.TemplateSet.Set(_worldPacket.ReadUInt32());
|
||||
|
||||
for (var i = 0; i < customizationCount; ++i)
|
||||
CreateInfo.Customizations[i].Read(_worldPacket);
|
||||
{
|
||||
CreateInfo.Customizations[i] = new ChrCustomizationChoice()
|
||||
{
|
||||
ChrCustomizationOptionID = _worldPacket.ReadUInt32(),
|
||||
ChrCustomizationChoiceID = _worldPacket.ReadUInt32()
|
||||
};
|
||||
}
|
||||
|
||||
CreateInfo.Customizations.Sort();
|
||||
}
|
||||
|
||||
public CharacterCreateInfo CreateInfo;
|
||||
@@ -470,7 +462,15 @@ namespace Game.Networking.Packets
|
||||
var customizationCount = _worldPacket.ReadUInt32();
|
||||
|
||||
for (var i = 0; i < customizationCount; ++i)
|
||||
CustomizeInfo.Customizations[i].Read(_worldPacket);
|
||||
{
|
||||
CustomizeInfo.Customizations[i] = new ChrCustomizationChoice()
|
||||
{
|
||||
ChrCustomizationOptionID = _worldPacket.ReadUInt32(),
|
||||
ChrCustomizationChoiceID = _worldPacket.ReadUInt32()
|
||||
};
|
||||
}
|
||||
|
||||
CustomizeInfo.Customizations.Sort();
|
||||
|
||||
CustomizeInfo.CharName = _worldPacket.ReadString(_worldPacket.ReadBits<uint>(6));
|
||||
}
|
||||
@@ -499,7 +499,15 @@ namespace Game.Networking.Packets
|
||||
RaceOrFactionChangeInfo.Name = _worldPacket.ReadString(nameLength);
|
||||
|
||||
for (var i = 0; i < customizationCount; ++i)
|
||||
RaceOrFactionChangeInfo.Customizations[i].Read(_worldPacket);
|
||||
{
|
||||
RaceOrFactionChangeInfo.Customizations[i] = new ChrCustomizationChoice()
|
||||
{
|
||||
ChrCustomizationOptionID = _worldPacket.ReadUInt32(),
|
||||
ChrCustomizationChoiceID = _worldPacket.ReadUInt32()
|
||||
};
|
||||
}
|
||||
|
||||
RaceOrFactionChangeInfo.Customizations.Sort();
|
||||
}
|
||||
|
||||
public CharRaceOrFactionChangeInfo RaceOrFactionChangeInfo;
|
||||
@@ -527,7 +535,10 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteString(Display.Value.Name);
|
||||
|
||||
foreach (ChrCustomizationChoice customization in Display.Value.Customizations)
|
||||
customization.Write(_worldPacket);
|
||||
{
|
||||
_worldPacket.WriteUInt32(customization.ChrCustomizationOptionID);
|
||||
_worldPacket.WriteUInt32(customization.ChrCustomizationChoiceID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -839,7 +850,15 @@ namespace Game.Networking.Packets
|
||||
NewSex = _worldPacket.ReadUInt8();
|
||||
|
||||
for (var i = 0; i < customizationCount; ++i)
|
||||
Customizations[i].Read(_worldPacket);
|
||||
{
|
||||
Customizations[i] = new ChrCustomizationChoice()
|
||||
{
|
||||
ChrCustomizationOptionID = _worldPacket.ReadUInt32(),
|
||||
ChrCustomizationChoiceID = _worldPacket.ReadUInt32()
|
||||
};
|
||||
}
|
||||
|
||||
Customizations.Sort();
|
||||
}
|
||||
|
||||
public byte NewSex;
|
||||
@@ -981,7 +1000,10 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteUInt8(SexID);
|
||||
_worldPacket.WriteInt32(Customizations.Count);
|
||||
foreach (ChrCustomizationChoice customization in Customizations)
|
||||
customization.Write(_worldPacket);
|
||||
{
|
||||
_worldPacket.WriteUInt32(customization.ChrCustomizationOptionID);
|
||||
_worldPacket.WriteUInt32(customization.ChrCustomizationChoiceID);
|
||||
}
|
||||
|
||||
_worldPacket.WriteBits(CharName.GetByteCount(), 6);
|
||||
_worldPacket.FlushBits();
|
||||
@@ -1047,30 +1069,6 @@ namespace Game.Networking.Packets
|
||||
}
|
||||
|
||||
//Structs
|
||||
public struct ChrCustomizationChoice
|
||||
{
|
||||
public uint ChrCustomizationOptionID;
|
||||
public uint ChrCustomizationChoiceID;
|
||||
|
||||
public ChrCustomizationChoice(uint chrCustomizationOptionID, uint chrCustomizationChoiceID)
|
||||
{
|
||||
ChrCustomizationOptionID = chrCustomizationOptionID;
|
||||
ChrCustomizationChoiceID = chrCustomizationChoiceID;
|
||||
}
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt32(ChrCustomizationOptionID);
|
||||
data.WriteUInt32(ChrCustomizationChoiceID);
|
||||
}
|
||||
|
||||
public void Read(WorldPacket data)
|
||||
{
|
||||
ChrCustomizationOptionID = data.ReadUInt32();
|
||||
ChrCustomizationChoiceID = data.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
public class CharacterCreateInfo
|
||||
{
|
||||
// User specified variables
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Game.Networking.Packets
|
||||
|
||||
class GarrisonMapDataResponse : ServerPacket
|
||||
{
|
||||
public GarrisonMapDataResponse() : base(ServerOpcodes.GarrisonBuildingLandmarks, ConnectionType.Instance) { }
|
||||
public GarrisonMapDataResponse() : base(ServerOpcodes.GarrisonMapDataResponse, ConnectionType.Instance) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
|
||||
@@ -280,7 +280,7 @@ namespace Game.Networking.Packets
|
||||
|
||||
public class GuildEventStatusChange : ServerPacket
|
||||
{
|
||||
public GuildEventStatusChange() : base(ServerOpcodes.GuildEventAwayChange) { }
|
||||
public GuildEventStatusChange() : base(ServerOpcodes.GuildEventStatusChange) { }
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
|
||||
@@ -233,12 +233,12 @@ namespace Game.Networking.Packets
|
||||
GUID = player.GetGUID();
|
||||
SpecializationID = player.GetPrimarySpecialization();
|
||||
Name = player.GetName();
|
||||
GenderID = player.m_playerData.NativeSex;
|
||||
GenderID = (byte)player.GetNativeSex();
|
||||
Race = (byte)player.GetRace();
|
||||
ClassID = (byte)player.GetClass();
|
||||
|
||||
foreach (var customization in player.m_playerData.Customizations)
|
||||
Customizations.Add(new ChrCustomizationChoice(customization.ChrCustomizationOptionID, customization.ChrCustomizationChoiceID));
|
||||
Customizations.Add(customization);
|
||||
|
||||
for (byte i = 0; i < EquipmentSlot.End; ++i)
|
||||
{
|
||||
@@ -261,7 +261,10 @@ namespace Game.Networking.Packets
|
||||
data.WriteString(Name);
|
||||
|
||||
foreach (var customization in Customizations)
|
||||
customization.Write(data);
|
||||
{
|
||||
data.WriteUInt32(customization.ChrCustomizationOptionID);
|
||||
data.WriteUInt32(customization.ChrCustomizationChoiceID);
|
||||
}
|
||||
|
||||
foreach (InspectItemData item in Items)
|
||||
item.Write(data);
|
||||
|
||||
@@ -790,7 +790,7 @@ namespace Game.Networking.Packets
|
||||
|
||||
public class ItemModList
|
||||
{
|
||||
public Array<ItemMod> Values = new Array<ItemMod>(ItemModifier.Max);
|
||||
public Array<ItemMod> Values = new Array<ItemMod>((int)ItemModifier.Max);
|
||||
|
||||
public void Read(WorldPacket data)
|
||||
{
|
||||
@@ -859,8 +859,8 @@ namespace Game.Networking.Packets
|
||||
ItemBonus.Value.Context = item.GetContext();
|
||||
}
|
||||
|
||||
foreach (var mod in item.m_itemData.Modifiers.Values)
|
||||
Modifications.Values.Add(mod.Value, (ItemModifier)mod.Type);
|
||||
foreach (var mod in item.m_itemData.Modifiers.GetValue().Values)
|
||||
Modifications.Values.Add(new ItemMod(mod.Value, (ItemModifier)mod.Type));
|
||||
}
|
||||
|
||||
public ItemInstance(Loots.LootItem lootItem)
|
||||
|
||||
@@ -328,7 +328,7 @@ namespace Game.Networking.Packets
|
||||
public class ClientGossipText
|
||||
{
|
||||
public uint QuestID;
|
||||
public int ContentTuningID;
|
||||
public uint ContentTuningID;
|
||||
public int QuestType;
|
||||
public bool Repeatable;
|
||||
public string QuestTitle;
|
||||
@@ -338,7 +338,7 @@ namespace Game.Networking.Packets
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt32(QuestID);
|
||||
data.WriteInt32(ContentTuningID);
|
||||
data.WriteUInt32(ContentTuningID);
|
||||
data.WriteInt32(QuestType);
|
||||
data.WriteUInt32(QuestFlags);
|
||||
data.WriteUInt32(QuestFlagsEx);
|
||||
|
||||
@@ -616,7 +616,7 @@ namespace Game.Networking.Packets
|
||||
BnetAccountID = player.GetSession().GetBattlenetAccountGUID();
|
||||
Name = player.GetName();
|
||||
RaceID = player.GetRace();
|
||||
Sex = (Gender)(byte)player.m_playerData.NativeSex;
|
||||
Sex = player.GetNativeSex();
|
||||
ClassID = player.GetClass();
|
||||
Level = (byte)player.GetLevel();
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteUInt32(Info.QuestID);
|
||||
_worldPacket.WriteInt32(Info.QuestType);
|
||||
_worldPacket.WriteUInt32(Info.QuestPackageID);
|
||||
_worldPacket.WriteInt32(Info.ContentTuningID);
|
||||
_worldPacket.WriteUInt32(Info.ContentTuningID);
|
||||
_worldPacket.WriteInt32(Info.QuestSortID);
|
||||
_worldPacket.WriteUInt32(Info.QuestInfoID);
|
||||
_worldPacket.WriteUInt32(Info.SuggestedGroupNum);
|
||||
@@ -350,7 +350,7 @@ namespace Game.Networking.Packets
|
||||
{
|
||||
QuestGiverGUID = _worldPacket.ReadPackedGuid();
|
||||
QuestID = _worldPacket.ReadUInt32();
|
||||
ItemChoiceID = _worldPacket.ReadUInt32();
|
||||
Choice.Read(_worldPacket);
|
||||
}
|
||||
|
||||
public ObjectGuid QuestGiverGUID;
|
||||
@@ -887,13 +887,19 @@ namespace Game.Networking.Packets
|
||||
|
||||
public struct QuestCompleteDisplaySpell
|
||||
{
|
||||
public int SpellID;
|
||||
public int PlayerConditionID;
|
||||
public uint SpellID;
|
||||
public uint PlayerConditionID;
|
||||
|
||||
public QuestCompleteDisplaySpell(uint spellID, uint playerConditionID)
|
||||
{
|
||||
SpellID = spellID;
|
||||
PlayerConditionID = playerConditionID;
|
||||
}
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteInt32(SpellID);
|
||||
data.WriteInt32(PlayerConditionID);
|
||||
data.WriteUInt32(SpellID);
|
||||
data.WriteUInt32(PlayerConditionID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -914,7 +920,7 @@ namespace Game.Networking.Packets
|
||||
|
||||
public uint QuestID;
|
||||
public int QuestType; // Accepted values: 0, 1 or 2. 0 == IsAutoComplete() (skip objectives/details)
|
||||
public int ContentTuningID;
|
||||
public uint ContentTuningID;
|
||||
public uint QuestPackageID;
|
||||
public int QuestSortID; // zone or sort to display in quest log
|
||||
public uint QuestInfoID;
|
||||
|
||||
@@ -933,7 +933,10 @@ namespace Game.Networking.Packets
|
||||
_worldPacket.WriteInt32(ItemDisplayID.Count);
|
||||
|
||||
foreach (ChrCustomizationChoice customization in Customizations)
|
||||
customization.Write(_worldPacket);
|
||||
{
|
||||
_worldPacket.WriteUInt32(customization.ChrCustomizationOptionID);
|
||||
_worldPacket.WriteUInt32(customization.ChrCustomizationChoiceID);
|
||||
}
|
||||
|
||||
foreach (var itemDisplayId in ItemDisplayID)
|
||||
_worldPacket.WriteInt32(itemDisplayId);
|
||||
@@ -1352,9 +1355,9 @@ namespace Game.Networking.Packets
|
||||
public struct SpellCastVisual
|
||||
{
|
||||
public uint SpellXSpellVisualID;
|
||||
public int ScriptVisualID;
|
||||
public uint ScriptVisualID;
|
||||
|
||||
public SpellCastVisual(uint spellXSpellVisualID, int scriptVisualID)
|
||||
public SpellCastVisual(uint spellXSpellVisualID, uint scriptVisualID)
|
||||
{
|
||||
SpellXSpellVisualID = spellXSpellVisualID;
|
||||
ScriptVisualID = scriptVisualID;
|
||||
@@ -1363,13 +1366,21 @@ namespace Game.Networking.Packets
|
||||
public void Read(WorldPacket data)
|
||||
{
|
||||
SpellXSpellVisualID = data.ReadUInt32();
|
||||
ScriptVisualID = data.ReadInt32();
|
||||
ScriptVisualID = data.ReadUInt32();
|
||||
}
|
||||
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteUInt32(SpellXSpellVisualID);
|
||||
data.WriteInt32(ScriptVisualID);
|
||||
data.WriteUInt32(ScriptVisualID);
|
||||
}
|
||||
|
||||
public static implicit operator SpellCastVisualField(SpellCastVisual spellCastVisual)
|
||||
{
|
||||
SpellCastVisualField visual;
|
||||
visual.SpellXSpellVisualID = spellCastVisual.SpellXSpellVisualID;
|
||||
visual.ScriptVisualID = spellCastVisual.ScriptVisualID;
|
||||
return visual;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-25
@@ -284,17 +284,16 @@ namespace Game
|
||||
if (questXp == null || RewardXPDifficulty >= 10)
|
||||
return 0;
|
||||
|
||||
float multiplier = 1.0f;
|
||||
if (questLevel != player.GetLevel())
|
||||
multiplier = CliDB.XpGameTable.GetRow(Math.Min(player.GetLevel(), questLevel)).Divisor / CliDB.XpGameTable.GetRow(player.GetLevel()).Divisor;
|
||||
|
||||
int diffFactor = (int)(2 * (questLevel + (Level == -1 ? 0 : 5) - player.GetLevel()) + 10);
|
||||
int diffFactor = (int)(2 * (questLevel - player.GetLevel()) + 12);
|
||||
if (diffFactor < 1)
|
||||
diffFactor = 1;
|
||||
else if (diffFactor > 10)
|
||||
diffFactor = 10;
|
||||
|
||||
uint xp = (uint)(diffFactor * questXp.Difficulty[RewardXPDifficulty] * RewardXPMultiplier / 10 * multiplier);
|
||||
uint xp = (uint)(diffFactor * questXp.Difficulty[RewardXPDifficulty] * RewardXPMultiplier / 10);
|
||||
if (player.GetLevel() >= Global.ObjectMgr.GetMaxLevelForExpansion(PlayerConst.CurrentExpansion - 1) && player.GetSession().GetExpansion() == PlayerConst.CurrentExpansion && Expansion < (int)PlayerConst.CurrentExpansion)
|
||||
xp = (uint)(xp / 9.0f);
|
||||
|
||||
if (xp <= 100)
|
||||
xp = 5 * ((xp + 2) / 5);
|
||||
else if (xp <= 500)
|
||||
@@ -329,7 +328,7 @@ namespace Game
|
||||
rewards.Title = RewardTitleId;
|
||||
rewards.FactionFlags = RewardReputationMask;
|
||||
|
||||
var displaySpellItr = rewards.SpellCompletionDisplayID.begin();
|
||||
var displaySpellIndex = 0;
|
||||
foreach (QuestRewardDisplaySpell displaySpell in RewardDisplaySpell)
|
||||
{
|
||||
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(displaySpell.PlayerConditionId);
|
||||
@@ -337,8 +336,8 @@ namespace Game
|
||||
if (!ConditionManager.IsPlayerMeetingCondition(player, playerCondition))
|
||||
continue;
|
||||
|
||||
displaySpellItr = displaySpell.SpellId;
|
||||
if (++displaySpellItr == null)
|
||||
rewards.SpellCompletionDisplayID[displaySpellIndex] = (int)displaySpell.SpellId;
|
||||
if (++displaySpellIndex >= rewards.SpellCompletionDisplayID.Length)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -456,11 +455,8 @@ namespace Game
|
||||
|
||||
QueryData.Info.QuestID = Id;
|
||||
QueryData.Info.QuestType = (int)Type;
|
||||
QueryData.Info.QuestLevel = Level;
|
||||
QueryData.Info.QuestScalingFactionGroup = ScalingFactionGroup;
|
||||
QueryData.Info.QuestMaxScalingLevel = MaxScalingLevel;
|
||||
QueryData.Info.ContentTuningID = ContentTuningId;
|
||||
QueryData.Info.QuestPackageID = PackageID;
|
||||
QueryData.Info.QuestMinLevel = MinLevel;
|
||||
QueryData.Info.QuestSortID = QuestSortID;
|
||||
QueryData.Info.QuestInfoID = QuestInfoID;
|
||||
QueryData.Info.SuggestedGroupNum = SuggestedPlayers;
|
||||
@@ -474,8 +470,8 @@ namespace Game
|
||||
QueryData.Info.RewardMoneyDifficulty = RewardMoneyDifficulty;
|
||||
QueryData.Info.RewardMoneyMultiplier = RewardMoneyMultiplier;
|
||||
QueryData.Info.RewardBonusMoney = RewardBonusMoney;
|
||||
for (byte i = 0; i < SharedConst.QuestRewardDisplaySpellCount; ++i)
|
||||
QueryData.Info.RewardDisplaySpell[i] = RewardDisplaySpell[i];
|
||||
foreach (QuestRewardDisplaySpell displaySpell in RewardDisplaySpell)
|
||||
QueryData.Info.RewardDisplaySpell.Add(new QuestCompleteDisplaySpell(displaySpell.SpellId, displaySpell.PlayerConditionId));
|
||||
|
||||
QueryData.Info.RewardSpell = RewardSpell;
|
||||
|
||||
@@ -581,15 +577,6 @@ namespace Game
|
||||
public void SetEventIdForQuest(ushort eventId) { _eventIdForQuest = eventId; }
|
||||
public ushort GetEventIdForQuest() { return _eventIdForQuest; }
|
||||
|
||||
[Obsolete]
|
||||
public int MinLevel;
|
||||
[Obsolete]
|
||||
public int Level;
|
||||
[Obsolete]
|
||||
public int ScalingFactionGroup;
|
||||
[Obsolete]
|
||||
public int MaxScalingLevel;
|
||||
|
||||
#region Fields
|
||||
public uint Id;
|
||||
public QuestType Type;
|
||||
@@ -699,7 +686,7 @@ namespace Game
|
||||
public uint ScriptId;
|
||||
|
||||
public List<uint> DependentPreviousQuests = new List<uint>();
|
||||
public QueryQuestInfoResponse[] QueryData = new QueryQuestInfoResponse[(int)Locale.Total];
|
||||
public QueryQuestInfoResponse QueryData;
|
||||
|
||||
uint _rewChoiceItemsCount;
|
||||
uint _rewItemsCount;
|
||||
|
||||
@@ -355,11 +355,11 @@ namespace Game
|
||||
Values[WorldCfg.CharacterCreatingDisabledRacemask] = GetDefaultValue("CharacterCreating.Disabled.RaceMask", 0);
|
||||
Values[WorldCfg.CharacterCreatingDisabledClassmask] = GetDefaultValue("CharacterCreating.Disabled.ClassMask", 0);
|
||||
|
||||
Values[WorldCfg.CharactersPerRealm] = GetDefaultValue("CharactersPerRealm", 16);
|
||||
if ((int)Values[WorldCfg.CharactersPerRealm] < 1 || (int)Values[WorldCfg.CharactersPerRealm] > 16)
|
||||
Values[WorldCfg.CharactersPerRealm] = GetDefaultValue("CharactersPerRealm", 50);
|
||||
if ((int)Values[WorldCfg.CharactersPerRealm] < 1 || (int)Values[WorldCfg.CharactersPerRealm] > 200)
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, "CharactersPerRealm ({0}) must be in range 1..16. Set to 16.", Values[WorldCfg.CharactersPerRealm]);
|
||||
Values[WorldCfg.CharactersPerRealm] = 16;
|
||||
Log.outError(LogFilter.ServerLoading, "CharactersPerRealm ({0}) must be in range 1..200. Set to 200.", Values[WorldCfg.CharactersPerRealm]);
|
||||
Values[WorldCfg.CharactersPerRealm] = 200;
|
||||
}
|
||||
|
||||
// must be after CharactersPerRealm
|
||||
@@ -370,14 +370,7 @@ namespace Game
|
||||
Values[WorldCfg.CharactersPerAccount] = Values[WorldCfg.CharactersPerRealm];
|
||||
}
|
||||
|
||||
Values[WorldCfg.DemonHuntersPerRealm] = GetDefaultValue("DemonHuntersPerRealm", 1);
|
||||
if ((int)Values[WorldCfg.DemonHuntersPerRealm] < 0 || (int)Values[WorldCfg.DemonHuntersPerRealm] > 12)
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, "DemonHuntersPerRealm ({0}) must be in range 0..12. Set to 1.", Values[WorldCfg.DemonHuntersPerRealm]);
|
||||
Values[WorldCfg.DemonHuntersPerRealm] = 1;
|
||||
}
|
||||
|
||||
Values[WorldCfg.CharacterCreatingMinLevelForDemonHunter] = GetDefaultValue("CharacterCreating.MinLevelForDemonHunter", 70);
|
||||
Values[WorldCfg.CharacterCreatingMinLevelForDemonHunter] = GetDefaultValue("CharacterCreating.MinLevelForDemonHunter", 0);
|
||||
|
||||
Values[WorldCfg.SkipCinematics] = GetDefaultValue("SkipCinematics", 0);
|
||||
if ((int)Values[WorldCfg.SkipCinematics] < 0 || (int)Values[WorldCfg.SkipCinematics] > 2)
|
||||
|
||||
@@ -663,6 +663,12 @@ namespace Game
|
||||
HandlePlayerLogin((LoginQueryHolder)_charLoginCallback.Result);
|
||||
_charLoginCallback = null;
|
||||
}
|
||||
|
||||
if (_charEnumCallback != null && _charEnumCallback.IsCompleted)
|
||||
{
|
||||
HandleCharEnum((EnumCharactersQueryHolder)_charEnumCallback.Result);
|
||||
_charEnumCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
TransactionCallback AddTransactionCallback(TransactionCallback callback)
|
||||
@@ -909,6 +915,7 @@ namespace Game
|
||||
Task<SQLQueryHolder<AccountInfoQueryLoad>> _realmAccountLoginCallback;
|
||||
Task<SQLQueryHolder<AccountInfoQueryLoad>> _accountLoginCallback;
|
||||
Task<SQLQueryHolder<PlayerLoginQueryLoad>> _charLoginCallback;
|
||||
Task<SQLQueryHolder<EnumCharacterQueryLoad>> _charEnumCallback;
|
||||
|
||||
AsyncCallbackProcessor<QueryCallback> _queryProcessor = new AsyncCallbackProcessor<QueryCallback>();
|
||||
AsyncCallbackProcessor<TransactionCallback> _transactionCallbacks = new AsyncCallbackProcessor<TransactionCallback>();
|
||||
|
||||
@@ -2501,13 +2501,13 @@ namespace Game.Spells
|
||||
if (!m_caster.ToPlayer().GetCommandStatus(PlayerCommandStates.Casttime))
|
||||
{
|
||||
// calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail)
|
||||
m_casttime = m_spellInfo.CalcCastTime(m_caster.GetLevel(), this);
|
||||
m_casttime = m_spellInfo.CalcCastTime(this);
|
||||
}
|
||||
else
|
||||
m_casttime = 0;
|
||||
}
|
||||
else
|
||||
m_casttime = m_spellInfo.CalcCastTime(m_caster.GetLevel(), this);
|
||||
m_casttime = m_spellInfo.CalcCastTime(this);
|
||||
|
||||
// don't allow channeled spells / spells with cast time to be casted while moving
|
||||
// exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING
|
||||
@@ -3547,7 +3547,7 @@ namespace Game.Spells
|
||||
owner.ToPlayer().SendPacket(petCastFailed);
|
||||
}
|
||||
|
||||
public static void SendCastResult(Player caster, SpellInfo spellInfo, SpellCastVisual spellVisual, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError = SpellCustomErrors.None, uint? param1 = null, uint? param2 = null)
|
||||
public static void SendCastResult(Player caster, SpellInfo spellInfo, Networking.Packets.SpellCastVisual spellVisual, ObjectGuid cast_count, SpellCastResult result, SpellCustomErrors customError = SpellCustomErrors.None, uint? param1 = null, uint? param2 = null)
|
||||
{
|
||||
if (result == SpellCastResult.SpellCastOk)
|
||||
return;
|
||||
@@ -4038,7 +4038,7 @@ namespace Game.Spells
|
||||
{
|
||||
m_caster.ClearChannelObjects();
|
||||
m_caster.SetChannelSpellId(0);
|
||||
m_caster.SetChannelSpellXSpellVisualId(default);
|
||||
m_caster.SetChannelVisual(default);
|
||||
}
|
||||
|
||||
SpellChannelUpdate spellChannelUpdate = new SpellChannelUpdate();
|
||||
@@ -4087,7 +4087,7 @@ namespace Game.Spells
|
||||
m_caster.AddChannelObject(target.targetGUID);
|
||||
|
||||
m_caster.SetChannelSpellId(m_spellInfo.Id);
|
||||
m_caster.SetChannelSpellXSpellVisualId(m_SpellVisual);
|
||||
m_caster.SetChannelVisual(m_SpellVisual);
|
||||
}
|
||||
|
||||
void SendResurrectRequest(Player target)
|
||||
@@ -7404,7 +7404,7 @@ namespace Game.Spells
|
||||
public bool m_fromClient;
|
||||
public SpellCastFlagsEx m_castFlagsEx;
|
||||
public SpellMisc m_misc;
|
||||
public SpellCastVisual m_SpellVisual;
|
||||
public Networking.Packets.SpellCastVisual m_SpellVisual;
|
||||
public SpellCastTargets m_targets;
|
||||
public sbyte m_comboPointGain;
|
||||
public SpellCustomErrors m_customError;
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace Game.Spells
|
||||
AttributesEx11 = (SpellAttr11)_misc.Attributes[11];
|
||||
AttributesEx12 = (SpellAttr12)_misc.Attributes[12];
|
||||
AttributesEx13 = (SpellAttr13)_misc.Attributes[13];
|
||||
AttributesEx14 = (SpellAttr14)_misc.Attributes[14];
|
||||
CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(_misc.CastingTimeIndex);
|
||||
DurationEntry = CliDB.SpellDurationStorage.LookupByKey(_misc.DurationIndex);
|
||||
RangeIndex = _misc.RangeIndex;
|
||||
@@ -2608,31 +2609,11 @@ namespace Game.Spells
|
||||
return (DurationEntry.MaxDuration == -1) ? -1 : Math.Abs(DurationEntry.MaxDuration);
|
||||
}
|
||||
|
||||
public int CalcCastTime(uint level = 0, Spell spell = null)
|
||||
public int CalcCastTime(Spell spell = null)
|
||||
{
|
||||
int castTime = 0;
|
||||
if (CastTimeEntry != null)
|
||||
{
|
||||
int calcLevel = spell != null ? (int)spell.GetCaster().GetLevel() : 0;
|
||||
if (MaxLevel != 0 && calcLevel > MaxLevel)
|
||||
calcLevel = (int)MaxLevel;
|
||||
|
||||
if (HasAttribute(SpellAttr13.Unk17))
|
||||
calcLevel *= 5;
|
||||
|
||||
if (MaxLevel != 0 && calcLevel > MaxLevel)
|
||||
calcLevel = (int)MaxLevel;
|
||||
|
||||
if (BaseLevel != 0)
|
||||
calcLevel -= (int)BaseLevel;
|
||||
|
||||
if (calcLevel < 0)
|
||||
calcLevel = 0;
|
||||
|
||||
castTime = (int)(CastTimeEntry.Base + CastTimeEntry.PerLevel * level);
|
||||
if (castTime < CastTimeEntry.Minimum)
|
||||
castTime = CastTimeEntry.Minimum;
|
||||
}
|
||||
castTime = Math.Max(CastTimeEntry.Base, CastTimeEntry.Minimum);
|
||||
|
||||
if (castTime <= 0)
|
||||
return 0;
|
||||
@@ -2963,7 +2944,7 @@ namespace Game.Spells
|
||||
}
|
||||
case SpellProcsPerMinuteModType.Class:
|
||||
{
|
||||
if (caster.GetClassMask().HasAnyFlag(mod.Param))
|
||||
if (caster.GetClassMask().HasAnyFlag((uint)mod.Param))
|
||||
ppm *= 1.0f + mod.Coeff;
|
||||
break;
|
||||
}
|
||||
@@ -3513,6 +3494,7 @@ namespace Game.Spells
|
||||
public bool HasAttribute(SpellAttr11 attribute) { return Convert.ToBoolean(AttributesEx11 & attribute); }
|
||||
public bool HasAttribute(SpellAttr12 attribute) { return Convert.ToBoolean(AttributesEx12 & attribute); }
|
||||
public bool HasAttribute(SpellAttr13 attribute) { return Convert.ToBoolean(AttributesEx13 & attribute); }
|
||||
public bool HasAttribute(SpellAttr14 attribute) { return Convert.ToBoolean(AttributesEx14 & attribute); }
|
||||
public bool HasAttribute(SpellCustomAttributes attribute) { return Convert.ToBoolean(AttributesCu & attribute); }
|
||||
|
||||
public bool HasAnyAuraInterruptFlag() { return AuraInterruptFlags.Any(flag => flag != 0); }
|
||||
@@ -3542,6 +3524,7 @@ namespace Game.Spells
|
||||
public SpellAttr11 AttributesEx11 { get; set; }
|
||||
public SpellAttr12 AttributesEx12 { get; set; }
|
||||
public SpellAttr13 AttributesEx13 { get; set; }
|
||||
public SpellAttr14 AttributesEx14 { get; set; }
|
||||
public SpellCustomAttributes AttributesCu { get; set; }
|
||||
public BitSet NegativeEffects { get; set; } = new BitSet(SpellConst.MaxEffects);
|
||||
public ulong Stances { get; set; }
|
||||
@@ -4359,6 +4342,18 @@ namespace Game.Spells
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 269 SPELL_EFFECT_UPGRADE_ITEM
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 270 SPELL_EFFECT_270
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 271 SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 272 SPELL_EFFECT_SET_COVENANT
|
||||
new StaticData(SpellEffectImplicitTargetTypes.Caster, SpellTargetObjectTypes.Unit), // 273 SPELL_EFFECT_CRAFT_RUNEFORGE_LEGENDARY
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 274 SPELL_EFFECT_274
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 275 SPELL_EFFECT_275
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 276 SPELL_EFFECT_LEARN_TRANSMOG_ILLUSION
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 277 SPELL_EFFECT_SET_CHROMIE_TIME
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 278 SPELL_EFFECT_270
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 279 SPELL_EFFECT_LEARN_GARR_TALENT
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 280 SPELL_EFFECT_270
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 281 SPELL_EFFECT_LEARN_SOULBIND_CONDUIT
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 282 SPELL_EFFECT_CONVERT_ITEMS_TO_CURRENCY
|
||||
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 283 SPELL_EFFECT_283
|
||||
};
|
||||
|
||||
#region Fields
|
||||
@@ -4726,7 +4721,8 @@ namespace Game.Spells
|
||||
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 147
|
||||
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 148
|
||||
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 149
|
||||
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 150
|
||||
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 150 TARGET_UNIT_OWN_CRITTER
|
||||
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 151
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user