BFA Update (still lots of testing to do tho)
This commit is contained in:
@@ -261,6 +261,7 @@ namespace Game.AI
|
||||
me.ResetPlayerDamageReq();
|
||||
me.SetLastDamagedTime(0);
|
||||
me.SetCannotReachTarget(false);
|
||||
me.DoNotReacquireTarget();
|
||||
|
||||
if (me.IsInEvadeMode())
|
||||
return false;
|
||||
|
||||
@@ -39,6 +39,12 @@ namespace Game.AI
|
||||
if (me.IsCharmed() && me.GetVictim() == me.GetCharmer())
|
||||
return true;
|
||||
|
||||
// dont allow pets to follow targets far away from owner
|
||||
Unit owner = me.GetCharmerOrOwner();
|
||||
if (owner)
|
||||
if (owner.GetExactDist(me) >= (owner.GetVisibilityRange() - 10.0f))
|
||||
return true;
|
||||
|
||||
return !me.IsValidAttackTarget(me.GetVictim());
|
||||
}
|
||||
|
||||
|
||||
@@ -2565,6 +2565,7 @@ namespace Game.AI
|
||||
public uint pointId;
|
||||
public uint transport;
|
||||
public uint disablePathfinding;
|
||||
public uint contactDistance;
|
||||
}
|
||||
public struct SendGossipMenu
|
||||
{
|
||||
|
||||
@@ -255,10 +255,10 @@ namespace Game.AI
|
||||
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate(e.Action.morphOrMount.creature);
|
||||
if (ci != null)
|
||||
{
|
||||
uint displayId = ObjectManager.ChooseDisplayId(ci);
|
||||
obj.ToCreature().SetDisplayId(displayId);
|
||||
CreatureModel model = ObjectManager.ChooseDisplayId(ci);
|
||||
obj.ToCreature().SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
|
||||
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {0}, GuidLow {1} set displayid to {2}",
|
||||
obj.GetEntry(), obj.GetGUID().ToString(), displayId);
|
||||
obj.GetEntry(), obj.GetGUID().ToString(), model.CreatureDisplayID);
|
||||
}
|
||||
}
|
||||
//if no param1, then use value from param2 (modelId)
|
||||
@@ -1133,7 +1133,7 @@ namespace Game.AI
|
||||
{
|
||||
CreatureTemplate cInfo = Global.ObjectMgr.GetCreatureTemplate(e.Action.morphOrMount.creature);
|
||||
if (cInfo != null)
|
||||
obj.ToUnit().Mount(ObjectManager.ChooseDisplayId(cInfo));
|
||||
obj.ToUnit().Mount(ObjectManager.ChooseDisplayId(cInfo).CreatureDisplayID);
|
||||
}
|
||||
else
|
||||
obj.ToUnit().Mount(e.Action.morphOrMount.model);
|
||||
@@ -1541,7 +1541,13 @@ namespace Game.AI
|
||||
me.GetMotionMaster().MovePoint(e.Action.moveToPos.pointId, x, y, z, e.Action.moveToPos.disablePathfinding == 0);
|
||||
}
|
||||
else
|
||||
me.GetMotionMaster().MovePoint(e.Action.moveToPos.pointId, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), e.Action.moveToPos.disablePathfinding == 0);
|
||||
{
|
||||
float x, y, z;
|
||||
target.GetPosition(out x, out y, out z);
|
||||
if (e.Action.moveToPos.contactDistance > 0)
|
||||
target.GetContactPoint(me, out x, out y, out z, e.Action.moveToPos.contactDistance);
|
||||
me.GetMotionMaster().MovePoint(e.Action.moveToPos.pointId, x, y, z, e.Action.moveToPos.disablePathfinding == 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SmartActions.RespawnTarget:
|
||||
|
||||
@@ -615,7 +615,7 @@ namespace Game.Achievements
|
||||
if (achievement.Flags.HasAnyFlag(AchievementFlags.RealmFirstReach | AchievementFlags.RealmFirstKill))
|
||||
{
|
||||
// broadcast realm first reached
|
||||
ServerFirstAchievement serverFirstAchievement = new ServerFirstAchievement();
|
||||
BroadcastAchievement serverFirstAchievement = new BroadcastAchievement();
|
||||
serverFirstAchievement.Name = _owner.GetName();
|
||||
serverFirstAchievement.PlayerGUID = _owner.GetGUID();
|
||||
serverFirstAchievement.AchievementID = achievement.Id;
|
||||
@@ -993,7 +993,7 @@ namespace Game.Achievements
|
||||
if (achievement.Flags.HasAnyFlag(AchievementFlags.RealmFirstReach | AchievementFlags.RealmFirstKill))
|
||||
{
|
||||
// broadcast realm first reached
|
||||
ServerFirstAchievement serverFirstAchievement = new ServerFirstAchievement();
|
||||
BroadcastAchievement serverFirstAchievement = new BroadcastAchievement();
|
||||
serverFirstAchievement.Name = _owner.GetName();
|
||||
serverFirstAchievement.PlayerGUID = _owner.GetGUID();
|
||||
serverFirstAchievement.AchievementID = achievement.Id;
|
||||
@@ -1147,22 +1147,21 @@ namespace Game.Achievements
|
||||
|
||||
_achievementRewards.Clear(); // need for reload case
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
SQLResult result = DB.World.Query("SELECT entry, title_A, title_H, item, sender, subject, text, mailTemplate FROM achievement_reward");
|
||||
// 0 1 2 3 4 5 6 7
|
||||
SQLResult result = DB.World.Query("SELECT ID, TitleA, TitleH, ItemID, Sender, Subject, Body, MailTemplateID FROM achievement_reward");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, ">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint entry = result.Read<uint>(0);
|
||||
AchievementRecord achievement = CliDB.AchievementStorage.LookupByKey(entry);
|
||||
uint id = result.Read<uint>(0);
|
||||
AchievementRecord achievement = CliDB.AchievementStorage.LookupByKey(id);
|
||||
if (achievement == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` contains a wrong achievement entry (Entry: {0}), ignored.", entry);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` contains a wrong achievement ID ({id}), ignored.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1178,19 +1177,19 @@ namespace Game.Achievements
|
||||
// must be title or mail at least
|
||||
if (reward.TitleId[0] == 0 && reward.TitleId[1] == 0 && reward.SenderCreatureId == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) does not contain title or item reward data. Ignored.", entry);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) does not contain title or item reward data. Ignored.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (achievement.Faction == AchievementFaction.Any && (reward.TitleId[0] == 0 ^ reward.TitleId[1] == 0))
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) contains the title (A: {1} H: {2}) for only one team.", entry, reward.TitleId[0], reward.TitleId[1]);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) contains the title (A: {reward.TitleId[0]} H: {reward.TitleId[1]}) for only one team.");
|
||||
|
||||
if (reward.TitleId[0] != 0)
|
||||
{
|
||||
CharTitlesRecord titleEntry = CliDB.CharTitlesStorage.LookupByKey(reward.TitleId[0]);
|
||||
if (titleEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) contains an invalid title id ({1}) in `title_A`, set to 0", entry, reward.TitleId[0]);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) contains an invalid title ID ({reward.TitleId[0]}) in `title_A`, set to 0");
|
||||
reward.TitleId[0] = 0;
|
||||
}
|
||||
}
|
||||
@@ -1200,7 +1199,7 @@ namespace Game.Achievements
|
||||
CharTitlesRecord titleEntry = CliDB.CharTitlesStorage.LookupByKey(reward.TitleId[1]);
|
||||
if (titleEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) contains an invalid title id ({1}) in `title_H`, set to 0", entry, reward.TitleId[1]);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) contains an invalid title ID ({reward.TitleId[1]}) in `title_H`, set to 0");
|
||||
reward.TitleId[1] = 0;
|
||||
}
|
||||
}
|
||||
@@ -1210,51 +1209,50 @@ namespace Game.Achievements
|
||||
{
|
||||
if (Global.ObjectMgr.GetCreatureTemplate(reward.SenderCreatureId) == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) contains an invalid creature entry {1} as sender, mail reward skipped.", entry, reward.SenderCreatureId);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) contains an invalid creature ID {reward.SenderCreatureId} as sender, mail reward skipped.");
|
||||
reward.SenderCreatureId = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reward.ItemId != 0)
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) does not have sender data, but contains an item reward. Item will not be rewarded.", entry);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) does not have sender data, but contains an item reward. Item will not be rewarded.");
|
||||
|
||||
if (!reward.Subject.IsEmpty())
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) does not have sender data, but contains a mail subject.", entry);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) does not have sender data, but contains a mail subject.");
|
||||
|
||||
if (!reward.Body.IsEmpty())
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) does not have sender data, but contains mail text.", entry);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) does not have sender data, but contains mail text.");
|
||||
|
||||
if (reward.MailTemplateId != 0)
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) does not have sender data, but has a MailTemplateId.", entry);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) does not have sender data, but has a MailTemplateId.");
|
||||
}
|
||||
|
||||
if (reward.MailTemplateId != 0)
|
||||
{
|
||||
if (!CliDB.MailTemplateStorage.ContainsKey(reward.MailTemplateId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) is using an invalid MailTemplateId ({1}).", entry, reward.MailTemplateId);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) is using an invalid MailTemplateId ({reward.MailTemplateId}).");
|
||||
reward.MailTemplateId = 0;
|
||||
}
|
||||
else if (!reward.Subject.IsEmpty() || !reward.Body.IsEmpty())
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) is using MailTemplateId ({1}) and mail subject/text.", entry, reward.MailTemplateId);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) is using MailTemplateId ({reward.MailTemplateId}) and mail subject/text.");
|
||||
}
|
||||
|
||||
if (reward.ItemId != 0)
|
||||
{
|
||||
if (Global.ObjectMgr.GetItemTemplate(reward.ItemId) == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward` (Entry: {0}) contains an invalid item id {1}, reward mail will not contain the rewarded item.", entry, reward.ItemId);
|
||||
Log.outError(LogFilter.Sql, $"Table `achievement_reward` (ID: {id}) contains an invalid item id {reward.ItemId}, reward mail will not contain the rewarded item.");
|
||||
reward.ItemId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_achievementRewards[entry] = reward;
|
||||
++count;
|
||||
_achievementRewards[id] = reward;
|
||||
}
|
||||
while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} achievement rewards in {1} ms.", count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} achievement rewards in {1} ms.", _achievementRewards.Count, Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
public void LoadRewardLocales()
|
||||
@@ -1263,34 +1261,34 @@ namespace Game.Achievements
|
||||
|
||||
_achievementRewardLocales.Clear(); // need for reload case
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT entry, subject_loc1, text_loc1, subject_loc2, text_loc2, subject_loc3, text_loc3, subject_loc4, text_loc4, " +
|
||||
"subject_loc5, text_loc5, subject_loc6, text_loc6, subject_loc7, text_loc7, subject_loc8, text_loc8 FROM locales_achievement_reward");
|
||||
// 0 1 2 3
|
||||
SQLResult result = DB.World.Query("SELECT ID, Locale, Subject, Body FROM achievement_reward_locale");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty.");
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 achievement reward locale strings. DB table `achievement_reward_locale` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
uint entry = result.Read<uint>(0);
|
||||
uint id = result.Read<uint>(0);
|
||||
string localeName = result.Read<string>(1);
|
||||
|
||||
if (!_achievementRewards.ContainsKey(entry))
|
||||
if (!_achievementRewards.ContainsKey(id))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `locales_achievement_reward` (Entry: {0}) contains locale strings for a non-existing achievement reward.", entry);
|
||||
Log.outError(LogFilter.Sql, "Table `achievement_reward_locale` (ID: {id}) contains locale strings for a non-existing achievement reward.");
|
||||
continue;
|
||||
}
|
||||
|
||||
AchievementRewardLocale data = new AchievementRewardLocale();
|
||||
LocaleConstant locale = localeName.ToEnum<LocaleConstant>();
|
||||
if (locale == LocaleConstant.enUS)
|
||||
continue;
|
||||
|
||||
for (int i = (int)LocaleConstant.OldTotal - 1; i > 0; --i)
|
||||
{
|
||||
LocaleConstant locale = (LocaleConstant)i;
|
||||
ObjectManager.AddLocaleString(result.Read<string>(1 + 2 * (i - 1)), locale, data.Subject);
|
||||
ObjectManager.AddLocaleString(result.Read<string>(1 + 2 * (i - 1) + 1), locale, data.Body);
|
||||
}
|
||||
ObjectManager.AddLocaleString(result.Read<string>(2), locale, data.Subject);
|
||||
ObjectManager.AddLocaleString(result.Read<string>(3), locale, data.Body);
|
||||
|
||||
_achievementRewardLocales[entry] = data;
|
||||
_achievementRewardLocales[id] = data;
|
||||
}
|
||||
while (result.NextRow());
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ namespace Game.Achievements
|
||||
SetCriteriaProgress(criteria, referencePlayer.GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
|
||||
break;
|
||||
case CriteriaTypes.EarnHonorableKill:
|
||||
SetCriteriaProgress(criteria, referencePlayer.GetUInt32Value(PlayerFields.LifetimeHonorableKills), referencePlayer);
|
||||
SetCriteriaProgress(criteria, referencePlayer.GetUInt32Value(ActivePlayerFields.LifetimeHonorableKills), referencePlayer);
|
||||
break;
|
||||
case CriteriaTypes.HighestGoldValueOwned:
|
||||
SetCriteriaProgress(criteria, referencePlayer.GetMoney(), referencePlayer, ProgressType.Highest);
|
||||
@@ -420,6 +420,9 @@ namespace Game.Achievements
|
||||
case CriteriaTypes.GainParagonReputation:
|
||||
case CriteriaTypes.EarnHonorXp:
|
||||
case CriteriaTypes.RelicTalentUnlocked:
|
||||
case CriteriaTypes.ReachAccountHonorLevel:
|
||||
case CriteriaTypes.HeartOfAzerothArtifactPowerEarned:
|
||||
case CriteriaTypes.HeartOfAzerothLevelReached:
|
||||
break; // Not implemented yet :(
|
||||
}
|
||||
|
||||
@@ -792,6 +795,9 @@ namespace Game.Achievements
|
||||
case CriteriaTypes.GainParagonReputation:
|
||||
case CriteriaTypes.EarnHonorXp:
|
||||
case CriteriaTypes.RelicTalentUnlocked:
|
||||
case CriteriaTypes.ReachAccountHonorLevel:
|
||||
case CriteriaTypes.HeartOfAzerothArtifactPowerEarned:
|
||||
case CriteriaTypes.HeartOfAzerothLevelReached:
|
||||
return progress.Counter >= requiredAmount;
|
||||
case CriteriaTypes.CompleteAchievement:
|
||||
case CriteriaTypes.CompleteQuest:
|
||||
@@ -1062,7 +1068,7 @@ namespace Game.Achievements
|
||||
continue;
|
||||
|
||||
uint mask = 1u << (int)((uint)area.AreaBit % 32);
|
||||
if (Convert.ToBoolean(referencePlayer.GetUInt32Value(PlayerFields.ExploredZones1 + playerIndexOffset) & mask))
|
||||
if (Convert.ToBoolean(referencePlayer.GetUInt32Value(ActivePlayerFields.ExploredZones + playerIndexOffset) & mask))
|
||||
{
|
||||
matchFound = true;
|
||||
break;
|
||||
@@ -1390,9 +1396,7 @@ namespace Game.Achievements
|
||||
return false;
|
||||
break;
|
||||
case CriteriaAdditionalCondition.PrestigeLevel: // 194
|
||||
if (!referencePlayer || referencePlayer.GetPrestigeLevel() != reqValue)
|
||||
return false;
|
||||
break;
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1907,7 +1911,7 @@ namespace Game.Achievements
|
||||
criteria.ID, criteria.Entry.Type, DataType, ClassRace.ClassId);
|
||||
return false;
|
||||
}
|
||||
if (ClassRace.RaceId != 0 && ((1 << (int)(ClassRace.RaceId - 1)) & (int)Race.RaceMaskAllPlayable) == 0)
|
||||
if (ClassRace.RaceId != 0 && ((1ul << (int)(ClassRace.RaceId - 1)) & (ulong)Race.RaceMaskAllPlayable) == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.",
|
||||
criteria.ID, criteria.Entry.Type, DataType, ClassRace.RaceId);
|
||||
@@ -2052,7 +2056,7 @@ namespace Game.Achievements
|
||||
criteria.ID, criteria.Entry.Type, DataType, ClassRace.ClassId);
|
||||
return false;
|
||||
}
|
||||
if (ClassRace.RaceId != 0 && ((1 << (int)(ClassRace.RaceId - 1)) & (int)Race.RaceMaskAllPlayable) == 0)
|
||||
if (ClassRace.RaceId != 0 && ((1ul << (int)(ClassRace.RaceId - 1)) & (ulong)Race.RaceMaskAllPlayable) == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `criteria_data` (Entry: {0} Type: {1}) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE ({2}) has non-existing race in value2 ({3}), ignored.",
|
||||
criteria.ID, criteria.Entry.Type, DataType, ClassRace.RaceId);
|
||||
|
||||
@@ -1235,9 +1235,10 @@ namespace Game.BattleGrounds
|
||||
{
|
||||
playerData.IsInWorld = true;
|
||||
playerData.PrimaryTalentTree = (int)player.GetUInt32Value(PlayerFields.CurrentSpecId);
|
||||
playerData.PrimaryTalentTreeNameIndex = 0;
|
||||
playerData.Sex = (int)player.GetGender();
|
||||
playerData.PlayerRace = player.GetRace();
|
||||
playerData.Prestige = player.GetPrestigeLevel();
|
||||
playerData.PlayerClass = (int)player.GetClass();
|
||||
playerData.HonorLevel = (int)player.GetHonorLevel();
|
||||
}
|
||||
|
||||
pvpLogData.Players.Add(playerData);
|
||||
|
||||
@@ -1019,7 +1019,7 @@ namespace Game.BattleGrounds.Zones
|
||||
public const int Berserkbuff2 = 17;
|
||||
public const int Max = 18;
|
||||
}
|
||||
struct WSGObjectEntry
|
||||
public sealed class WSGObjectEntry
|
||||
{
|
||||
public const uint DoorA1 = 179918;
|
||||
public const uint DoorA2 = 179919;
|
||||
|
||||
@@ -406,7 +406,7 @@ namespace Game.BattlePets
|
||||
return;
|
||||
|
||||
// TODO: set proper CreatureID for spell DEFAULT_SUMMON_BATTLE_PET_SPELL (default EffectMiscValueA is 40721 - Murkimus the Gladiator)
|
||||
_owner.GetPlayer().SetGuidValue(PlayerFields.SummonedBattlePetId, guid);
|
||||
_owner.GetPlayer().SetGuidValue(ActivePlayerFields.SummonedBattlePetId, guid);
|
||||
_owner.GetPlayer().CastSpell(_owner.GetPlayer(), speciesEntry.SummonSpellID != 0 ? speciesEntry.SummonSpellID : SharedConst.DefaultSummonBattlePetSpell);
|
||||
|
||||
// TODO: set pet level, quality... update fields
|
||||
@@ -416,10 +416,10 @@ namespace Game.BattlePets
|
||||
{
|
||||
Player ownerPlayer = _owner.GetPlayer();
|
||||
Creature pet = ObjectAccessor.GetCreatureOrPetOrVehicle(ownerPlayer, ownerPlayer.GetCritterGUID());
|
||||
if (pet && ownerPlayer.GetGuidValue(PlayerFields.SummonedBattlePetId) == pet.GetGuidValue(UnitFields.BattlePetCompanionGuid))
|
||||
if (pet && ownerPlayer.GetGuidValue(ActivePlayerFields.SummonedBattlePetId) == pet.GetGuidValue(UnitFields.BattlePetCompanionGuid))
|
||||
{
|
||||
pet.DespawnOrUnsummon();
|
||||
ownerPlayer.SetGuidValue(PlayerFields.SummonedBattlePetId, ObjectGuid.Empty);
|
||||
ownerPlayer.SetGuidValue(ActivePlayerFields.SummonedBattlePetId, ObjectGuid.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -265,6 +265,81 @@ namespace Game.Chat
|
||||
return true;
|
||||
}
|
||||
|
||||
[Command("changeaccount", RBACPermissions.CommandCharacterChangeaccount, true)]
|
||||
static bool HandleCharacterChangeAccountCommand(StringArguments args, CommandHandler handler)
|
||||
{
|
||||
string playerNameStr;
|
||||
string accountName;
|
||||
handler.extractOptFirstArg(args, out playerNameStr, out accountName);
|
||||
if (accountName.IsEmpty())
|
||||
return false;
|
||||
|
||||
ObjectGuid targetGuid;
|
||||
string targetName;
|
||||
Player playerNotUsed;
|
||||
if (!handler.extractPlayerTarget(new StringArguments(playerNameStr), out playerNotUsed, out targetGuid, out targetName))
|
||||
return false;
|
||||
|
||||
CharacterInfo characterInfo = Global.WorldMgr.GetCharacterInfo(targetGuid);
|
||||
if (characterInfo == null)
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.PlayerNotFound);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint oldAccountId = characterInfo.AccountId;
|
||||
uint newAccountId = oldAccountId;
|
||||
|
||||
PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_ACCOUNT_ID_BY_NAME);
|
||||
stmt.AddValue(0, accountName);
|
||||
SQLResult result = DB.Login.Query(stmt);
|
||||
if (!result.IsEmpty())
|
||||
newAccountId = result.Read<uint>(0);
|
||||
else
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.AccountNotExist, accountName);
|
||||
return false;
|
||||
}
|
||||
|
||||
// nothing to do :)
|
||||
if (newAccountId == oldAccountId)
|
||||
return true;
|
||||
|
||||
uint charCount = Global.AccountMgr.GetCharactersCount(newAccountId);
|
||||
if (charCount != 0)
|
||||
{
|
||||
if (charCount >= WorldConfig.GetIntValue(WorldCfg.CharactersPerRealm))
|
||||
{
|
||||
handler.SendSysMessage(CypherStrings.AccountCharacterListFull, accountName, newAccountId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_ACCOUNT_BY_GUID);
|
||||
stmt.AddValue(0, newAccountId);
|
||||
stmt.AddValue(1, targetGuid.GetCounter());
|
||||
DB.Characters.DirectExecute(stmt);
|
||||
|
||||
Global.WorldMgr.UpdateRealmCharCount(oldAccountId);
|
||||
Global.WorldMgr.UpdateRealmCharCount(newAccountId);
|
||||
|
||||
Global.WorldMgr.UpdateCharacterInfoAccount(targetGuid, newAccountId);
|
||||
|
||||
handler.SendSysMessage(CypherStrings.ChangeAccountSuccess, targetName, accountName);
|
||||
|
||||
string logString = $"changed ownership of player {targetName} ({targetGuid.ToString()}) from account {oldAccountId} to account {newAccountId}";
|
||||
WorldSession session = handler.GetSession();
|
||||
if (session != null)
|
||||
{
|
||||
Player player = session.GetPlayer();
|
||||
if (player != null)
|
||||
Log.outCommand(session.GetAccountId(), $"GM {player.GetName()} (Account: {session.GetAccountId()}) {logString}");
|
||||
}
|
||||
else
|
||||
Log.outCommand(0, $"{handler.GetCypherString(CypherStrings.Console)} {logString}");
|
||||
return true;
|
||||
}
|
||||
|
||||
[Command("changefaction", RBACPermissions.CommandCharacterChangefaction, true)]
|
||||
static bool HandleCharacterChangeFactionCommand(StringArguments args, CommandHandler handler)
|
||||
{
|
||||
@@ -702,7 +777,7 @@ namespace Game.Chat
|
||||
{
|
||||
player.GiveLevel((uint)newLevel);
|
||||
player.InitTalentForLevel();
|
||||
player.SetUInt32Value(PlayerFields.Xp, 0);
|
||||
player.SetUInt32Value(ActivePlayerFields.Xp, 0);
|
||||
|
||||
if (handler.needReportToTarget(player))
|
||||
{
|
||||
|
||||
@@ -245,9 +245,9 @@ namespace Game.Chat.Commands
|
||||
for (ushort i = 0; i < PlayerConst.ExploredZonesSize; ++i)
|
||||
{
|
||||
if (flag != 0)
|
||||
handler.GetSession().GetPlayer().SetFlag(PlayerFields.ExploredZones1 + i, 0xFFFFFFFF);
|
||||
handler.GetSession().GetPlayer().SetFlag(ActivePlayerFields.ExploredZones + i, 0xFFFFFFFF);
|
||||
else
|
||||
handler.GetSession().GetPlayer().SetFlag(PlayerFields.ExploredZones1 + i, 0);
|
||||
handler.GetSession().GetPlayer().SetFlag(ActivePlayerFields.ExploredZones + i, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1173,7 +1173,7 @@ namespace Game.Chat
|
||||
phaseShift.AddPhase(phase, PhaseFlags.None, null);
|
||||
|
||||
if (uint.TryParse(args.NextString(), out uint map))
|
||||
phaseShift.AddUiWorldMapAreaIdSwap(map);
|
||||
phaseShift.AddUiMapPhaseId(map);
|
||||
|
||||
PhasingHandler.SendToPlayer(handler.GetSession().GetPlayer(), phaseShift);
|
||||
return true;
|
||||
|
||||
@@ -542,7 +542,11 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
if (handler.GetSession() != null)
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id, qInfo.Level, title, statusStr);
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id,
|
||||
handler.GetSession().GetPlayer().GetQuestLevel(qInfo),
|
||||
handler.GetSession().GetPlayer().GetQuestMinLevel(qInfo),
|
||||
qInfo.MaxScalingLevel, qInfo.ScalingFactionGroup,
|
||||
title, statusStr);
|
||||
else
|
||||
handler.SendSysMessage(CypherStrings.QuestListConsole, qInfo.Id, title, statusStr);
|
||||
|
||||
@@ -590,7 +594,11 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
if (handler.GetSession() != null)
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id, qInfo.Level, _title, statusStr);
|
||||
handler.SendSysMessage(CypherStrings.QuestListChat, qInfo.Id, qInfo.Id,
|
||||
handler.GetSession().GetPlayer().GetQuestLevel(qInfo),
|
||||
handler.GetSession().GetPlayer().GetQuestMinLevel(qInfo),
|
||||
qInfo.MaxScalingLevel, qInfo.ScalingFactionGroup,
|
||||
_title, statusStr);
|
||||
else
|
||||
handler.SendSysMessage(CypherStrings.QuestListConsole, qInfo.Id, _title, statusStr);
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace Game.Chat
|
||||
float zoneX = obj.GetPositionX();
|
||||
float zoneY = obj.GetPositionY();
|
||||
|
||||
Global.DB2Mgr.Map2ZoneCoordinates(zoneId, ref zoneX, ref zoneY);
|
||||
Global.DB2Mgr.Map2ZoneCoordinates((int)zoneId, ref zoneX, ref zoneY);
|
||||
|
||||
Map map = obj.GetMap();
|
||||
float groundZ = map.GetHeight(obj.GetPhaseShift(), obj.GetPositionX(), obj.GetPositionY(), MapConst.MaxHeight);
|
||||
@@ -1189,8 +1189,8 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
uint val = (1u << (area.AreaBit % 32));
|
||||
uint currFields = playerTarget.GetUInt32Value(PlayerFields.ExploredZones1 + offset);
|
||||
playerTarget.SetUInt32Value(PlayerFields.ExploredZones1 + offset, (currFields | val));
|
||||
uint currFields = playerTarget.GetUInt32Value(ActivePlayerFields.ExploredZones + offset);
|
||||
playerTarget.SetUInt32Value(ActivePlayerFields.ExploredZones + offset, (currFields | val));
|
||||
|
||||
handler.SendSysMessage(CypherStrings.ExploreArea);
|
||||
return true;
|
||||
@@ -1230,8 +1230,8 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
uint val = (1u << (area.AreaBit % 32));
|
||||
uint currFields = playerTarget.GetUInt32Value(PlayerFields.ExploredZones1 + offset);
|
||||
playerTarget.SetUInt32Value(PlayerFields.ExploredZones1 + offset, (currFields ^ val));
|
||||
uint currFields = playerTarget.GetUInt32Value(ActivePlayerFields.ExploredZones + offset);
|
||||
playerTarget.SetUInt32Value(ActivePlayerFields.ExploredZones + offset, (currFields ^ val));
|
||||
|
||||
handler.SendSysMessage(CypherStrings.UnexploreArea);
|
||||
return true;
|
||||
|
||||
@@ -215,7 +215,11 @@ namespace Game.Chat
|
||||
if (CheckModifySpeed(args, handler, target, out Scale, 0.1f, 10.0f, false))
|
||||
{
|
||||
NotifyModification(handler, target, CypherStrings.YouChangeSize, CypherStrings.YoursSizeChanged, Scale);
|
||||
target.SetObjectScale(Scale);
|
||||
Creature creatureTarget = target.ToCreature();
|
||||
if (creatureTarget)
|
||||
creatureTarget.SetFloatValue(UnitFields.DisplayScale, Scale);
|
||||
else
|
||||
target.SetObjectScale(Scale);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
// .addquest #entry'
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level:min_level:max_level:scaling_faction|h[name]|h|r
|
||||
string cId = handler.extractKeyFromLink(args, "Hquest");
|
||||
if (!uint.TryParse(cId, out uint entry))
|
||||
return false;
|
||||
@@ -78,7 +78,7 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
// .quest complete #entry
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level:min_level:max_level:scaling_faction|h[name]|h|r
|
||||
string cId = handler.extractKeyFromLink(args, "Hquest");
|
||||
if (!uint.TryParse(cId, out uint entry))
|
||||
return false;
|
||||
@@ -170,7 +170,7 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
// .removequest #entry'
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level:min_level:max_level:scaling_faction|h[name]|h|r
|
||||
string cId = handler.extractKeyFromLink(args, "Hquest");
|
||||
if (!uint.TryParse(cId, out uint entry))
|
||||
return false;
|
||||
@@ -224,7 +224,7 @@ namespace Game.Chat
|
||||
}
|
||||
|
||||
// .quest reward #entry
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level|h[name]|h|r
|
||||
// number or [name] Shift-click form |color|Hquest:quest_id:quest_level:min_level:max_level:scaling_faction|h[name]|h|r
|
||||
string cId = handler.extractKeyFromLink(args, "Hquest");
|
||||
if (!uint.TryParse(cId, out uint entry))
|
||||
return false;
|
||||
|
||||
@@ -51,8 +51,8 @@ namespace Game.Chat
|
||||
if (!handler.extractPlayerTarget(args, out target))
|
||||
return false;
|
||||
|
||||
target.SetUInt32Value(PlayerFields.Kills, 0);
|
||||
target.SetUInt32Value(PlayerFields.LifetimeHonorableKills, 0);
|
||||
target.SetUInt32Value(ActivePlayerFields.Kills, 0);
|
||||
target.SetUInt32Value(ActivePlayerFields.LifetimeHonorableKills, 0);
|
||||
target.UpdateCriteria(CriteriaTypes.EarnHonorableKill);
|
||||
|
||||
return true;
|
||||
@@ -85,7 +85,7 @@ namespace Game.Chat
|
||||
player.SetUInt32Value(UnitFields.Flags, (uint)UnitFlags.PvpAttackable);
|
||||
|
||||
//-1 is default value
|
||||
player.SetUInt32Value(PlayerFields.WatchedFactionIndex, 0xFFFFFFFF);
|
||||
player.SetUInt32Value(ActivePlayerFields.WatchedFactionIndex, 0xFFFFFFFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Game.Chat
|
||||
target.InitStatsForLevel(true);
|
||||
target.InitTaxiNodesForLevel();
|
||||
target.InitTalentForLevel();
|
||||
target.SetUInt32Value(PlayerFields.Xp, 0);
|
||||
target.SetUInt32Value(ActivePlayerFields.Xp, 0);
|
||||
|
||||
target._ApplyAllLevelScaleItemMods(true);
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace Game.Chat.Commands
|
||||
|
||||
titles &= ~titles2; // remove not existed titles
|
||||
|
||||
target.SetUInt64Value(PlayerFields.KnownTitles, titles);
|
||||
target.SetUInt64Value(ActivePlayerFields.KnownTitles, titles);
|
||||
handler.SendSysMessage(CypherStrings.Done);
|
||||
|
||||
if (!target.HasTitle(target.GetUInt32Value(PlayerFields.ChosenTitle)))
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Framework.Constants;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -168,7 +169,7 @@ namespace Game.Collision
|
||||
|
||||
public class MapRayCallback : WorkerCallback
|
||||
{
|
||||
public MapRayCallback(ModelInstance[] val)
|
||||
public MapRayCallback(ModelInstance[] val, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
prims = val;
|
||||
hit = false;
|
||||
@@ -177,7 +178,7 @@ namespace Game.Collision
|
||||
{
|
||||
if (prims[entry] == null)
|
||||
return false;
|
||||
bool result = prims[entry].intersectRay(ray, ref distance, pStopAtFirstHit);
|
||||
bool result = prims[entry].intersectRay(ray, ref distance, pStopAtFirstHit, flags);
|
||||
if (result)
|
||||
hit = true;
|
||||
return result;
|
||||
@@ -186,6 +187,7 @@ namespace Game.Collision
|
||||
|
||||
ModelInstance[] prims;
|
||||
bool hit;
|
||||
ModelIgnoreFlags flags;
|
||||
}
|
||||
|
||||
public class AreaInfoCallback : WorkerCallback
|
||||
@@ -236,7 +238,7 @@ namespace Game.Collision
|
||||
|
||||
public override bool Invoke(Ray r, IModel obj, ref float distance)
|
||||
{
|
||||
_didHit = obj.IntersectRay(r, ref distance, true, _phaseShift);
|
||||
_didHit = obj.IntersectRay(r, ref distance, true, _phaseShift, ModelIgnoreFlags.Nothing);
|
||||
return _didHit;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,13 @@ namespace Game.Collision
|
||||
Ignored
|
||||
}
|
||||
|
||||
public enum LoadResult
|
||||
{
|
||||
Success,
|
||||
FileNotFound,
|
||||
VersionMismatch
|
||||
}
|
||||
|
||||
public class VMapManager : Singleton<VMapManager>
|
||||
{
|
||||
VMapManager() { }
|
||||
@@ -124,7 +131,7 @@ namespace Game.Collision
|
||||
}
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2)
|
||||
public bool isInLineOfSight(uint mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
if (!isLineOfSightCalcEnabled() || Global.DisableMgr.IsDisabledFor(DisableType.VMAP, mapId, null, DisableFlags.VmapLOS))
|
||||
return true;
|
||||
@@ -135,7 +142,7 @@ namespace Game.Collision
|
||||
Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1);
|
||||
Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2);
|
||||
if (pos1 != pos2)
|
||||
return instanceTree.isInLineOfSight(pos1, pos2);
|
||||
return instanceTree.isInLineOfSight(pos1, pos2, ignoreFlags);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -232,7 +239,7 @@ namespace Game.Collision
|
||||
return false;
|
||||
}
|
||||
|
||||
public WorldModel acquireModelInstance(string filename)
|
||||
public WorldModel acquireModelInstance(string filename, uint flags = 0)
|
||||
{
|
||||
lock (LoadedModelFilesLock)
|
||||
{
|
||||
@@ -248,6 +255,9 @@ namespace Game.Collision
|
||||
}
|
||||
|
||||
Log.outDebug(LogFilter.Maps, "VMapManager: loading file '{0}'", filename);
|
||||
|
||||
worldmodel.Flags = flags;
|
||||
|
||||
model = new ManagedModel();
|
||||
model.setModel(worldmodel);
|
||||
|
||||
@@ -277,7 +287,7 @@ namespace Game.Collision
|
||||
}
|
||||
}
|
||||
|
||||
public bool existsMap(uint mapId, uint x, uint y)
|
||||
public LoadResult existsMap(uint mapId, uint x, uint y)
|
||||
{
|
||||
return StaticMapTree.CanLoadMap(VMapPath, mapId, x, y, this);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace Game.Collision
|
||||
if (result)
|
||||
{
|
||||
// acquire model instance
|
||||
WorldModel model = vm.acquireModelInstance(spawn.name);
|
||||
WorldModel model = vm.acquireModelInstance(spawn.name, spawn.flags);
|
||||
if (model == null)
|
||||
Log.outError(LogFilter.Server, "StaticMapTree.LoadMapTile() : could not acquire WorldModel [{0}, {1}]", tileX, tileY);
|
||||
|
||||
@@ -243,29 +243,29 @@ namespace Game.Collision
|
||||
return new FileStream(tilefile, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
|
||||
public static bool CanLoadMap(string vmapPath, uint mapID, uint tileX, uint tileY, VMapManager vm)
|
||||
public static LoadResult CanLoadMap(string vmapPath, uint mapID, uint tileX, uint tileY, VMapManager vm)
|
||||
{
|
||||
string fullname = vmapPath + VMapManager.getMapFileName(mapID);
|
||||
if (!File.Exists(fullname))
|
||||
return false;
|
||||
return LoadResult.FileNotFound;
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(new FileStream(fullname, FileMode.Open, FileAccess.Read)))
|
||||
{
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
return false;
|
||||
return LoadResult.VersionMismatch;
|
||||
}
|
||||
|
||||
FileStream stream = OpenMapTileFile(vmapPath, mapID, tileX, tileY, vm);
|
||||
if (stream == null)
|
||||
return false;
|
||||
return LoadResult.FileNotFound;
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
if (reader.ReadStringFromChars(8) != MapConst.VMapMagic)
|
||||
return false;
|
||||
return LoadResult.VersionMismatch;
|
||||
}
|
||||
|
||||
return true;
|
||||
return LoadResult.Success;
|
||||
}
|
||||
|
||||
public static string getTileFileName(uint mapID, uint tileX, uint tileY)
|
||||
@@ -307,15 +307,15 @@ namespace Game.Collision
|
||||
Vector3 dir = new Vector3(0, 0, -1);
|
||||
Ray ray = new Ray(pPos, dir); // direction with length of 1
|
||||
float maxDist = maxSearchDist;
|
||||
if (getIntersectionTime(ray, ref maxDist, false))
|
||||
if (getIntersectionTime(ray, ref maxDist, false, ModelIgnoreFlags.Nothing))
|
||||
height = pPos.Z - maxDist;
|
||||
|
||||
return height;
|
||||
}
|
||||
bool getIntersectionTime(Ray pRay, ref float pMaxDist, bool pStopAtFirstHit)
|
||||
bool getIntersectionTime(Ray pRay, ref float pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
float distance = pMaxDist;
|
||||
MapRayCallback intersectionCallBack = new MapRayCallback(iTreeValues);
|
||||
MapRayCallback intersectionCallBack = new MapRayCallback(iTreeValues, ignoreFlags);
|
||||
iTree.intersectRay(pRay, intersectionCallBack, ref distance, pStopAtFirstHit);
|
||||
if (intersectionCallBack.didHit())
|
||||
pMaxDist = distance;
|
||||
@@ -337,7 +337,7 @@ namespace Game.Collision
|
||||
Vector3 dir = (pPos2 - pPos1) / maxDist; // direction with length of 1
|
||||
Ray ray = new Ray(pPos1, dir);
|
||||
float dist = maxDist;
|
||||
if (getIntersectionTime(ray, ref dist, false))
|
||||
if (getIntersectionTime(ray, ref dist, false, ModelIgnoreFlags.Nothing))
|
||||
{
|
||||
pResultHitPos = pPos1 + dir * dist;
|
||||
if (pModifyDist < 0)
|
||||
@@ -365,7 +365,7 @@ namespace Game.Collision
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool isInLineOfSight(Vector3 pos1, Vector3 pos2)
|
||||
public bool isInLineOfSight(Vector3 pos1, Vector3 pos2, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
float maxDist = (pos2 - pos1).magnitude();
|
||||
// return false if distance is over max float, in case of cheater teleporting to the end of the universe
|
||||
@@ -380,7 +380,7 @@ namespace Game.Collision
|
||||
return true;
|
||||
// direction with length of 1
|
||||
Ray ray = new Ray(pos1, (pos2 - pos1) / maxDist);
|
||||
if (getIntersectionTime(ray, ref maxDist, true))
|
||||
if (getIntersectionTime(ray, ref maxDist, true, ignoreFlags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Game.Collision
|
||||
return mdl;
|
||||
}
|
||||
|
||||
public override bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift)
|
||||
public override bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
if (!isCollisionEnabled() || !owner.IsSpawned())
|
||||
return false;
|
||||
@@ -104,7 +104,7 @@ namespace Game.Collision
|
||||
Vector3 p = iInvRot * (ray.Origin - iPos) * iInvScale;
|
||||
Ray modRay = new Ray(p, iInvRot * ray.Direction);
|
||||
float distance = maxDist * iInvScale;
|
||||
bool hit = iModel.IntersectRay(modRay, ref distance, stopAtFirstHit);
|
||||
bool hit = iModel.IntersectRay(modRay, ref distance, stopAtFirstHit, ignoreFlags);
|
||||
if (hit)
|
||||
{
|
||||
distance *= iScale;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
using Framework.GameMath;
|
||||
using System.Collections.Generic;
|
||||
using Framework.Constants;
|
||||
|
||||
namespace Game.Collision
|
||||
{
|
||||
@@ -25,7 +26,8 @@ namespace Game.Collision
|
||||
public virtual Vector3 getPosition() { return default(Vector3); }
|
||||
public virtual AxisAlignedBox getBounds() { return default(AxisAlignedBox); }
|
||||
|
||||
public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float maxDist, bool stopAtFirstHit, PhaseShift phaseShift, ModelIgnoreFlags ignoreFlags) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) { return false; }
|
||||
public virtual bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit) { return false; }
|
||||
public virtual void IntersectPoint(Vector3 point, AreaInfo info, PhaseShift phaseShift) { }
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using System;
|
||||
using System.IO;
|
||||
@@ -93,7 +94,7 @@ namespace Game.Collision
|
||||
iInvScale = 1.0f / iScale;
|
||||
}
|
||||
|
||||
public bool intersectRay(Ray pRay, ref float pMaxDist, bool pStopAtFirstHit)
|
||||
public bool intersectRay(Ray pRay, ref float pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
if (iModel == null)
|
||||
return false;
|
||||
@@ -106,7 +107,7 @@ namespace Game.Collision
|
||||
Vector3 p = iInvRot * (pRay.Origin - iPos) * iInvScale;
|
||||
Ray modRay = new Ray(p, iInvRot * pRay.Direction);
|
||||
float distance = pMaxDist * iInvScale;
|
||||
bool hit = iModel.IntersectRay(modRay, ref distance, pStopAtFirstHit);
|
||||
bool hit = iModel.IntersectRay(modRay, ref distance, pStopAtFirstHit, ignoreFlags);
|
||||
if (hit)
|
||||
{
|
||||
distance *= iScale;
|
||||
|
||||
@@ -312,8 +312,16 @@ namespace Game.Collision
|
||||
RootWMOID = 0;
|
||||
}
|
||||
|
||||
public override bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit)
|
||||
public override bool IntersectRay(Ray ray, ref float distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags)
|
||||
{
|
||||
// If the caller asked us to ignore certain objects we should check flags
|
||||
if ((ignoreFlags & ModelIgnoreFlags.M2) != ModelIgnoreFlags.Nothing)
|
||||
{
|
||||
// M2 models are not taken into account for LoS calculation if caller requested their ignoring.
|
||||
if ((Flags & (uint)ModelFlags.M2) != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// small M2 workaround, maybe better make separate class with virtual intersection funcs
|
||||
// in any case, there's no need to use a bound tree if we only have one submodel
|
||||
if (groupModels.Count == 1)
|
||||
@@ -404,5 +412,6 @@ namespace Game.Collision
|
||||
List<GroupModel> groupModels = new List<GroupModel>();
|
||||
BIH groupTree = new BIH();
|
||||
uint RootWMOID;
|
||||
public uint Flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,23 @@ namespace Game.Combat
|
||||
}
|
||||
}
|
||||
|
||||
// delete all references out of specified range
|
||||
public void deleteReferencesOutOfRange(float range)
|
||||
{
|
||||
HostileReference refe = getFirst();
|
||||
range = range * range;
|
||||
while (refe != null)
|
||||
{
|
||||
HostileReference nextRef = refe.next();
|
||||
Unit owner = refe.GetSource().GetOwner();
|
||||
if (!owner.isActiveObject() && owner.GetExactDist2dSq(getOwner()) > range)
|
||||
{
|
||||
refe.removeReference();
|
||||
}
|
||||
refe = nextRef;
|
||||
}
|
||||
}
|
||||
|
||||
public new HostileReference getFirst() { return ((HostileReference)base.getFirst()); }
|
||||
|
||||
public void updateThreatTables()
|
||||
|
||||
@@ -1229,7 +1229,7 @@ namespace Game
|
||||
}
|
||||
case ConditionTypes.Class:
|
||||
{
|
||||
if (!Convert.ToBoolean(cond.ConditionValue1 & (uint)Class.ClassMaskAllPlayable))
|
||||
if (Convert.ToBoolean(cond.ConditionValue1 & ~(uint)Class.ClassMaskAllPlayable))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "{0} has non existing classmask ({1}), skipped.", cond.ToString(true), cond.ConditionValue1 & ~(uint)Class.ClassMaskAllPlayable);
|
||||
return false;
|
||||
@@ -1238,7 +1238,7 @@ namespace Game
|
||||
}
|
||||
case ConditionTypes.Race:
|
||||
{
|
||||
if (!Convert.ToBoolean(cond.ConditionValue1 & (uint)Race.RaceMaskAllPlayable))
|
||||
if (Convert.ToBoolean(cond.ConditionValue1 & ~(uint)Race.RaceMaskAllPlayable))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "{0} has non existing racemask ({1}), skipped.", cond.ToString(true), cond.ConditionValue1 & ~(uint)Race.RaceMaskAllPlayable);
|
||||
return false;
|
||||
@@ -1785,10 +1785,10 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
if (condition.PvpMedal != 0 && !Convert.ToBoolean((1 << (condition.PvpMedal - 1)) & player.GetUInt32Value(PlayerFields.PvpMedals)))
|
||||
if (condition.PvpMedal != 0 && !Convert.ToBoolean((1 << (condition.PvpMedal - 1)) & player.GetUInt32Value(ActivePlayerFields.PvpMedals)))
|
||||
return false;
|
||||
|
||||
if (condition.LifetimeMaxPVPRank != 0 && player.GetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetLifetimeMaxPvpRank) != condition.LifetimeMaxPVPRank)
|
||||
if (condition.LifetimeMaxPVPRank != 0 && player.GetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetLifetimeMaxPvpRank) != condition.LifetimeMaxPVPRank)
|
||||
return false;
|
||||
|
||||
if (condition.MovementFlags[0] != 0 && !Convert.ToBoolean((uint)player.GetUnitMovementFlags() & condition.MovementFlags[0]))
|
||||
@@ -1841,7 +1841,7 @@ namespace Game
|
||||
{
|
||||
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(condition.PrevQuestID[i]);
|
||||
if (questBit != 0)
|
||||
results[i] = (player.GetUInt32Value(PlayerFields.QuestCompleted + (int)((questBit - 1) >> 5)) & (1 << (int)((questBit - 1) & 31))) != 0;
|
||||
results[i] = (player.GetUInt32Value(ActivePlayerFields.QuestCompleted + (int)((questBit - 1) >> 5)) & (1 << (int)((questBit - 1) & 31))) != 0;
|
||||
}
|
||||
|
||||
if (!PlayerConditionLogic(condition.PrevQuestLogic, results))
|
||||
@@ -1920,7 +1920,7 @@ namespace Game
|
||||
{
|
||||
AreaTableRecord area = CliDB.AreaTableStorage.LookupByKey(condition.Explored[i]);
|
||||
if (area != null)
|
||||
if (area.AreaBit != -1 && !Convert.ToBoolean(player.GetUInt32Value(PlayerFields.ExploredZones1 + area.AreaBit / 32) & (1 << (area.AreaBit % 32))))
|
||||
if (area.AreaBit != -1 && !Convert.ToBoolean(player.GetUInt32Value(ActivePlayerFields.ExploredZones + area.AreaBit / 32) & (1 << (area.AreaBit % 32))))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2114,13 +2114,13 @@ namespace Game
|
||||
new ConditionTypeInfo("Realm Achievement", true, false, false),
|
||||
new ConditionTypeInfo("In Water", false,false, false),
|
||||
new ConditionTypeInfo("Terrain Swap", true, false, false),
|
||||
new ConditionTypeInfo("Sit/stand state", true, true, false),
|
||||
new ConditionTypeInfo("Sit/stand state", true, true, false),
|
||||
new ConditionTypeInfo("Daily Quest Completed",true, false, false),
|
||||
new ConditionTypeInfo("Charmed", false,false, false),
|
||||
new ConditionTypeInfo("Pet type", true, false, false),
|
||||
new ConditionTypeInfo("On Taxi", false, false, false),
|
||||
new ConditionTypeInfo("Quest state mask", true, true, false),
|
||||
new ConditionTypeInfo("Objective Complete", true, false, false)
|
||||
new ConditionTypeInfo("On Taxi", false,false, false),
|
||||
new ConditionTypeInfo("Quest state mask", true, true, false),
|
||||
new ConditionTypeInfo("Objective Complete", true, false, false)
|
||||
};
|
||||
|
||||
public struct ConditionTypeInfo
|
||||
|
||||
@@ -150,8 +150,8 @@ namespace Game.DataStorage
|
||||
while (templates.NextRow());
|
||||
}
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
SQLResult areatriggerSpellMiscs = DB.World.Query("SELECT SpellMiscId, AreaTriggerId, MoveCurveId, ScaleCurveId, MorphCurveId, FacingCurveId, DecalPropertiesId, TimeToTarget, TimeToTargetScale FROM `spell_areatrigger`");
|
||||
// 0 1 2 3 4 5 6 7 8 9 10
|
||||
SQLResult areatriggerSpellMiscs = DB.World.Query("SELECT SpellMiscId, AreaTriggerId, MoveCurveId, ScaleCurveId, MorphCurveId, FacingCurveId, AnimId, AnimKitId, DecalPropertiesId, TimeToTarget, TimeToTargetScale FROM `spell_areatrigger`");
|
||||
if (!areatriggerSpellMiscs.IsEmpty())
|
||||
{
|
||||
do
|
||||
@@ -184,10 +184,12 @@ namespace Game.DataStorage
|
||||
miscTemplate.MorphCurveId = ValidateAndSetCurve(areatriggerSpellMiscs.Read<uint>(4));
|
||||
miscTemplate.FacingCurveId = ValidateAndSetCurve(areatriggerSpellMiscs.Read<uint>(5));
|
||||
|
||||
miscTemplate.DecalPropertiesId = areatriggerSpellMiscs.Read<uint>(6);
|
||||
miscTemplate.AnimId = areatriggerSpellMiscs.Read<uint>(6);
|
||||
miscTemplate.AnimKitId = areatriggerSpellMiscs.Read<uint>(7);
|
||||
miscTemplate.DecalPropertiesId = areatriggerSpellMiscs.Read<uint>(8);
|
||||
|
||||
miscTemplate.TimeToTarget = areatriggerSpellMiscs.Read<uint>(7);
|
||||
miscTemplate.TimeToTargetScale = areatriggerSpellMiscs.Read<uint>(8);
|
||||
miscTemplate.TimeToTarget = areatriggerSpellMiscs.Read<uint>(9);
|
||||
miscTemplate.TimeToTargetScale = areatriggerSpellMiscs.Read<uint>(10);
|
||||
|
||||
miscTemplate.SplinePoints = splinesBySpellMisc[miscTemplate.MiscId];
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace Game.DataStorage
|
||||
DataPath = dataPath + "/dbc/" + defaultLocale + "/";
|
||||
|
||||
AchievementStorage = DBReader.Read<AchievementRecord>("Achievement.db2", HotfixStatements.SEL_ACHIEVEMENT, HotfixStatements.SEL_ACHIEVEMENT_LOCALE);
|
||||
AnimationDataStorage = DBReader.Read<AnimationDataRecord>("AnimationData.db2", HotfixStatements.SEL_ANIMATION_DATA);
|
||||
AnimKitStorage = DBReader.Read<AnimKitRecord>("AnimKit.db2", HotfixStatements.SEL_ANIM_KIT);
|
||||
AreaGroupMemberStorage = DBReader.Read<AreaGroupMemberRecord>("AreaGroupMember.db2", HotfixStatements.SEL_AREA_GROUP_MEMBER);
|
||||
AreaTableStorage = DBReader.Read<AreaTableRecord>("AreaTable.db2", HotfixStatements.SEL_AREA_TABLE, HotfixStatements.SEL_AREA_TABLE_LOCALE);
|
||||
@@ -74,6 +75,7 @@ namespace Game.DataStorage
|
||||
ChrSpecializationStorage = DBReader.Read<ChrSpecializationRecord>("ChrSpecialization.db2", HotfixStatements.SEL_CHR_SPECIALIZATION, HotfixStatements.SEL_CHR_SPECIALIZATION_LOCALE);
|
||||
CinematicCameraStorage = DBReader.Read<CinematicCameraRecord>("CinematicCamera.db2", HotfixStatements.SEL_CINEMATIC_CAMERA);
|
||||
CinematicSequencesStorage = DBReader.Read<CinematicSequencesRecord>("CinematicSequences.db2", HotfixStatements.SEL_CINEMATIC_SEQUENCES);
|
||||
ContentTuningStorage = DBReader.Read<ContentTuningRecord>("ContentTuning.db2", HotfixStatements.SEL_CONTENT_TUNING);
|
||||
ConversationLineStorage = DBReader.Read<ConversationLineRecord>("ConversationLine.db2", HotfixStatements.SEL_CONVERSATION_LINE);
|
||||
CreatureDisplayInfoStorage = DBReader.Read<CreatureDisplayInfoRecord>("CreatureDisplayInfo.db2", HotfixStatements.SEL_CREATURE_DISPLAY_INFO);
|
||||
CreatureDisplayInfoExtraStorage = DBReader.Read<CreatureDisplayInfoExtraRecord>("CreatureDisplayInfoExtra.db2", HotfixStatements.SEL_CREATURE_DISPLAY_INFO_EXTRA);
|
||||
@@ -93,6 +95,8 @@ namespace Game.DataStorage
|
||||
EmotesStorage = DBReader.Read<EmotesRecord>("Emotes.db2", HotfixStatements.SEL_EMOTES);
|
||||
EmotesTextStorage = DBReader.Read<EmotesTextRecord>("EmotesText.db2", HotfixStatements.SEL_EMOTES_TEXT);
|
||||
EmotesTextSoundStorage = DBReader.Read<EmotesTextSoundRecord>("EmotesTextSound.db2", HotfixStatements.SEL_EMOTES_TEXT_SOUND);
|
||||
ExpectedStatStorage = DBReader.Read <ExpectedStatRecord>("ExpectedStat.db2", HotfixStatements.SEL_EXPECTED_STAT);
|
||||
ExpectedStatModStorage = DBReader.Read <ExpectedStatModRecord>("ExpectedStatMod.db2", HotfixStatements.SEL_EXPECTED_STAT_MOD);
|
||||
FactionStorage = DBReader.Read<FactionRecord>("Faction.db2", HotfixStatements.SEL_FACTION, HotfixStatements.SEL_FACTION_LOCALE);
|
||||
FactionTemplateStorage = DBReader.Read<FactionTemplateRecord>("FactionTemplate.db2", HotfixStatements.SEL_FACTION_TEMPLATE);
|
||||
GameObjectDisplayInfoStorage = DBReader.Read<GameObjectDisplayInfoRecord>("GameObjectDisplayInfo.db2", HotfixStatements.SEL_GAMEOBJECT_DISPLAY_INFO);
|
||||
@@ -103,7 +107,7 @@ namespace Game.DataStorage
|
||||
GarrClassSpecStorage = DBReader.Read<GarrClassSpecRecord>("GarrClassSpec.db2", HotfixStatements.SEL_GARR_CLASS_SPEC, HotfixStatements.SEL_GARR_CLASS_SPEC_LOCALE);
|
||||
GarrFollowerStorage = DBReader.Read<GarrFollowerRecord>("GarrFollower.db2", HotfixStatements.SEL_GARR_FOLLOWER, HotfixStatements.SEL_GARR_FOLLOWER_LOCALE);
|
||||
GarrFollowerXAbilityStorage = DBReader.Read<GarrFollowerXAbilityRecord>("GarrFollowerXAbility.db2", HotfixStatements.SEL_GARR_FOLLOWER_X_ABILITY);
|
||||
GarrPlotStorage = DBReader.Read<GarrPlotRecord>("GarrPlot.db2", HotfixStatements.SEL_GARR_PLOT, HotfixStatements.SEL_GARR_PLOT_LOCALE);
|
||||
GarrPlotStorage = DBReader.Read<GarrPlotRecord>("GarrPlot.db2", HotfixStatements.SEL_GARR_PLOT);
|
||||
GarrPlotBuildingStorage = DBReader.Read<GarrPlotBuildingRecord>("GarrPlotBuilding.db2", HotfixStatements.SEL_GARR_PLOT_BUILDING);
|
||||
GarrPlotInstanceStorage = DBReader.Read<GarrPlotInstanceRecord>("GarrPlotInstance.db2", HotfixStatements.SEL_GARR_PLOT_INSTANCE);
|
||||
GarrSiteLevelStorage = DBReader.Read<GarrSiteLevelRecord>("GarrSiteLevel.db2", HotfixStatements.SEL_GARR_SITE_LEVEL);
|
||||
@@ -177,6 +181,7 @@ namespace Game.DataStorage
|
||||
NamesProfanityStorage = DBReader.Read<NamesProfanityRecord>("NamesProfanity.db2", HotfixStatements.SEL_NAMES_PROFANITY);
|
||||
NamesReservedStorage = DBReader.Read<NamesReservedRecord>("NamesReserved.db2", HotfixStatements.SEL_NAMES_RESERVED, HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
|
||||
NamesReservedLocaleStorage = DBReader.Read<NamesReservedLocaleRecord>("NamesReservedLocale.db2", HotfixStatements.SEL_NAMES_RESERVED_LOCALE);
|
||||
NumTalentsAtLevelStorage = DBReader.Read<NumTalentsAtLevelRecord>("NumTalentsAtLevel.db2", HotfixStatements.SEL_NUM_TALENTS_AT_LEVEL);
|
||||
OverrideSpellDataStorage = DBReader.Read<OverrideSpellDataRecord>("OverrideSpellData.db2", HotfixStatements.SEL_OVERRIDE_SPELL_DATA);
|
||||
PhaseStorage = DBReader.Read<PhaseRecord>("Phase.db2", HotfixStatements.SEL_PHASE);
|
||||
PhaseXPhaseGroupStorage = DBReader.Read<PhaseXPhaseGroupRecord>("PhaseXPhaseGroup.db2", HotfixStatements.SEL_PHASE_X_PHASE_GROUP);
|
||||
@@ -186,9 +191,9 @@ namespace Game.DataStorage
|
||||
PrestigeLevelInfoStorage = DBReader.Read<PrestigeLevelInfoRecord>("PrestigeLevelInfo.db2", HotfixStatements.SEL_PRESTIGE_LEVEL_INFO, HotfixStatements.SEL_PRESTIGE_LEVEL_INFO_LOCALE);
|
||||
PvpDifficultyStorage = DBReader.Read<PvpDifficultyRecord>("PVPDifficulty.db2", HotfixStatements.SEL_PVP_DIFFICULTY);
|
||||
PvpItemStorage = DBReader.Read<PvpItemRecord>("PVPItem.db2", HotfixStatements.SEL_PVP_ITEM);
|
||||
PvpRewardStorage = DBReader.Read<PvpRewardRecord>("PvpReward.db2", HotfixStatements.SEL_PVP_REWARD);
|
||||
PvpTalentStorage = DBReader.Read<PvpTalentRecord>("PvpTalent.db2", HotfixStatements.SEL_PVP_TALENT, HotfixStatements.SEL_PVP_TALENT_LOCALE);
|
||||
PvpTalentUnlockStorage = DBReader.Read<PvpTalentUnlockRecord>("PvpTalentUnlock.db2", HotfixStatements.SEL_PVP_TALENT_UNLOCK);
|
||||
PvpTalentCategoryStorage = DBReader.Read<PvpTalentCategoryRecord>("PvpTalentCategory.db2", HotfixStatements.SEL_PVP_TALENT_CATEGORY);
|
||||
PvpTalentSlotUnlockStorage = DBReader.Read<PvpTalentSlotUnlockRecord>("PvpTalentSlotUnlock.db2", HotfixStatements.SEL_PVP_TALENT_SLOT_UNLOCK);
|
||||
QuestFactionRewardStorage = DBReader.Read<QuestFactionRewardRecord>("QuestFactionReward.db2", HotfixStatements.SEL_QUEST_FACTION_REWARD);
|
||||
QuestMoneyRewardStorage = DBReader.Read<QuestMoneyRewardRecord>("QuestMoneyReward.db2", HotfixStatements.SEL_QUEST_MONEY_REWARD);
|
||||
QuestPackageItemStorage = DBReader.Read<QuestPackageItemRecord>("QuestPackageItem.db2", HotfixStatements.SEL_QUEST_PACKAGE_ITEM);
|
||||
@@ -200,7 +205,6 @@ namespace Game.DataStorage
|
||||
RewardPackXCurrencyTypeStorage = DBReader.Read<RewardPackXCurrencyTypeRecord>("RewardPackXCurrencyType.db2", HotfixStatements.SEL_REWARD_PACK_X_CURRENCY_TYPE);
|
||||
RewardPackXItemStorage = DBReader.Read<RewardPackXItemRecord>("RewardPackXItem.db2", HotfixStatements.SEL_REWARD_PACK_X_ITEM);
|
||||
RulesetItemUpgradeStorage = DBReader.Read<RulesetItemUpgradeRecord>("RulesetItemUpgrade.db2", HotfixStatements.SEL_RULESET_ITEM_UPGRADE);
|
||||
SandboxScalingStorage = DBReader.Read<SandboxScalingRecord>("SandboxScaling.db2", HotfixStatements.SEL_SANDBOX_SCALING);
|
||||
ScalingStatDistributionStorage = DBReader.Read<ScalingStatDistributionRecord>("ScalingStatDistribution.db2", HotfixStatements.SEL_SCALING_STAT_DISTRIBUTION);
|
||||
ScenarioStorage = DBReader.Read<ScenarioRecord>("Scenario.db2", HotfixStatements.SEL_SCENARIO, HotfixStatements.SEL_SCENARIO_LOCALE);
|
||||
ScenarioStepStorage = DBReader.Read<ScenarioStepRecord>("ScenarioStep.db2", HotfixStatements.SEL_SCENARIO_STEP, HotfixStatements.SEL_SCENARIO_STEP_LOCALE);
|
||||
@@ -213,7 +217,7 @@ namespace Game.DataStorage
|
||||
SkillRaceClassInfoStorage = DBReader.Read<SkillRaceClassInfoRecord>("SkillRaceClassInfo.db2", HotfixStatements.SEL_SKILL_RACE_CLASS_INFO);
|
||||
SoundKitStorage = DBReader.Read<SoundKitRecord>("SoundKit.db2", HotfixStatements.SEL_SOUND_KIT);
|
||||
SpecializationSpellsStorage = DBReader.Read<SpecializationSpellsRecord>("SpecializationSpells.db2", HotfixStatements.SEL_SPECIALIZATION_SPELLS, HotfixStatements.SEL_SPECIALIZATION_SPELLS_LOCALE);
|
||||
SpellStorage = DBReader.Read<SpellRecord>("Spell.db2", HotfixStatements.SEL_SPELL, HotfixStatements.SEL_SPELL_LOCALE);
|
||||
SpellNameStorage = DBReader.Read<SpellNameRecord>("SpellName.db2", HotfixStatements.SEL_SPELL_NAME, HotfixStatements.SEL_SPELL_NAME_LOCALE);
|
||||
SpellAuraOptionsStorage = DBReader.Read<SpellAuraOptionsRecord>("SpellAuraOptions.db2", HotfixStatements.SEL_SPELL_AURA_OPTIONS);
|
||||
SpellAuraRestrictionsStorage = DBReader.Read<SpellAuraRestrictionsRecord>("SpellAuraRestrictions.db2", HotfixStatements.SEL_SPELL_AURA_RESTRICTIONS);
|
||||
SpellCastTimesStorage = DBReader.Read<SpellCastTimesRecord>("SpellCastTimes.db2", HotfixStatements.SEL_SPELL_CAST_TIMES);
|
||||
@@ -259,14 +263,16 @@ namespace Game.DataStorage
|
||||
TransmogSetItemStorage = DBReader.Read<TransmogSetItemRecord>("TransmogSetItem.db2", HotfixStatements.SEL_TRANSMOG_SET_ITEM);
|
||||
TransportAnimationStorage = DBReader.Read<TransportAnimationRecord>("TransportAnimation.db2", HotfixStatements.SEL_TRANSPORT_ANIMATION);
|
||||
TransportRotationStorage = DBReader.Read<TransportRotationRecord>("TransportRotation.db2", HotfixStatements.SEL_TRANSPORT_ROTATION);
|
||||
UiMapStorage = DBReader.Read<UiMapRecord>("UiMap.db2", HotfixStatements.SEL_UI_MAP, HotfixStatements.SEL_UI_MAP_LOCALE);
|
||||
UiMapAssignmentStorage = DBReader.Read<UiMapAssignmentRecord>("UiMapAssignment.db2", HotfixStatements.SEL_UI_MAP_ASSIGNMENT);
|
||||
UiMapLinkStorage = DBReader.Read<UiMapLinkRecord>("UiMapLink.db2", HotfixStatements.SEL_UI_MAP_LINK);
|
||||
UiMapXMapArtStorage = DBReader.Read<UiMapXMapArtRecord>("UiMapXMapArt.db2", HotfixStatements.SEL_UI_MAP_X_MAP_ART);
|
||||
UnitPowerBarStorage = DBReader.Read<UnitPowerBarRecord>("UnitPowerBar.db2", HotfixStatements.SEL_UNIT_POWER_BAR, HotfixStatements.SEL_UNIT_POWER_BAR_LOCALE);
|
||||
VehicleStorage = DBReader.Read<VehicleRecord>("Vehicle.db2", HotfixStatements.SEL_VEHICLE);
|
||||
VehicleSeatStorage = DBReader.Read<VehicleSeatRecord>("VehicleSeat.db2", HotfixStatements.SEL_VEHICLE_SEAT);
|
||||
WMOAreaTableStorage = DBReader.Read<WMOAreaTableRecord>("WMOAreaTable.db2", HotfixStatements.SEL_WMO_AREA_TABLE, HotfixStatements.SEL_WMO_AREA_TABLE_LOCALE);
|
||||
WorldEffectStorage = DBReader.Read<WorldEffectRecord>("WorldEffect.db2", HotfixStatements.SEL_WORLD_EFFECT);
|
||||
WorldMapAreaStorage = DBReader.Read<WorldMapAreaRecord>("WorldMapArea.db2", HotfixStatements.SEL_WORLD_MAP_AREA);
|
||||
WorldMapOverlayStorage = DBReader.Read<WorldMapOverlayRecord>("WorldMapOverlay.db2", HotfixStatements.SEL_WORLD_MAP_OVERLAY);
|
||||
WorldMapTransformsStorage = DBReader.Read<WorldMapTransformsRecord>("WorldMapTransforms.db2", HotfixStatements.SEL_WORLD_MAP_TRANSFORMS);
|
||||
WorldSafeLocsStorage = DBReader.Read<WorldSafeLocsRecord>("WorldSafeLocs.db2", HotfixStatements.SEL_WORLD_SAFE_LOCS, HotfixStatements.SEL_WORLD_SAFE_LOCS_LOCALE);
|
||||
|
||||
foreach (var entry in TaxiPathStorage.Values)
|
||||
@@ -298,7 +304,7 @@ namespace Game.DataStorage
|
||||
continue;
|
||||
|
||||
// valid taxi network node
|
||||
byte field = (byte)((node.Id - 1) / 8);
|
||||
uint field = (node.Id - 1) / 8;
|
||||
byte submask = (byte)(1 << (int)((node.Id - 1) % 8));
|
||||
|
||||
TaxiNodesMask[field] |= submask;
|
||||
@@ -307,22 +313,24 @@ namespace Game.DataStorage
|
||||
if (node.Flags.HasAnyFlag(TaxiNodeFlags.Alliance))
|
||||
AllianceTaxiNodesMask[field] |= submask;
|
||||
|
||||
uint nodeMap;
|
||||
Global.DB2Mgr.DeterminaAlternateMapPosition(node.ContinentID, node.Pos.X, node.Pos.Y, node.Pos.Z, out nodeMap);
|
||||
if (nodeMap < 2)
|
||||
int uiMapId;
|
||||
if (!Global.DB2Mgr.GetUiMapPosition(node.Pos.X, node.Pos.Y, node.Pos.Z, node.ContinentID, 0, 0, 0, UiMapSystem.Adventure, false, out uiMapId))
|
||||
Global.DB2Mgr.GetUiMapPosition(node.Pos.X, node.Pos.Y, node.Pos.Z, node.ContinentID, 0, 0, 0, UiMapSystem.Taxi, false, out uiMapId);
|
||||
|
||||
if (uiMapId == 985 || uiMapId == 986)
|
||||
OldContinentsNodesMask[field] |= submask;
|
||||
}
|
||||
|
||||
Global.DB2Mgr.LoadStores();
|
||||
|
||||
// Check loaded DB2 files proper version
|
||||
if (!AreaTableStorage.ContainsKey(9531) || // last area (areaflag) added in 7.0.3 (22594)
|
||||
!CharTitlesStorage.ContainsKey(522) || // last char title added in 7.0.3 (22594)
|
||||
!GemPropertiesStorage.ContainsKey(3632) || // last gem property added in 7.0.3 (22594)
|
||||
!ItemStorage.ContainsKey(157831) || // last item added in 7.0.3 (22594)
|
||||
!ItemExtendedCostStorage.ContainsKey(6300) || // last item extended cost added in 7.0.3 (22594)
|
||||
!MapStorage.ContainsKey(1903) || // last map added in 7.0.3 (22594)
|
||||
!SpellStorage.ContainsKey(263166)) // last spell added in 7.0.3 (22594)
|
||||
if (!AreaTableStorage.ContainsKey(10048) || // last area added in 8.0.1 (28153)
|
||||
!CharTitlesStorage.ContainsKey(633) || // last char title added in 8.0.1 (28153)
|
||||
!GemPropertiesStorage.ContainsKey(3745) || // last gem property added in 8.0.1 (28153)
|
||||
!ItemStorage.ContainsKey(164760) || // last item added in 8.0.1 (28153)
|
||||
!ItemExtendedCostStorage.ContainsKey(6448) || // last item extended cost added in 8.0.1 (28153)
|
||||
!MapStorage.ContainsKey(2103) || // last map added in 8.0.1 (28153)
|
||||
!SpellNameStorage.ContainsKey(281872)) // last spell added in 8.0.1 (28153)
|
||||
{
|
||||
Log.outError(LogFilter.Misc, "You have _outdated_ DB2 files. Please extract correct versions from current using client.");
|
||||
Global.WorldMgr.ShutdownServ(10, ShutdownMask.Force, ShutdownExitCode.Error);
|
||||
@@ -346,7 +354,6 @@ namespace Game.DataStorage
|
||||
CombatRatingsGameTable = GameTableReader.Read<GtCombatRatingsRecord>("CombatRatings.txt");
|
||||
CombatRatingsMultByILvlGameTable = GameTableReader.Read<GtCombatRatingsMultByILvlRecord>("CombatRatingsMultByILvl.txt");
|
||||
ItemSocketCostPerLevelGameTable = GameTableReader.Read<GtItemSocketCostPerLevelRecord>("ItemSocketCostPerLevel.txt");
|
||||
HonorLevelGameTable = GameTableReader.Read<GtHonorLevelRecord>("HonorLevel.txt");
|
||||
HpPerStaGameTable = GameTableReader.Read<GtHpPerStaRecord>("HpPerSta.txt");
|
||||
NpcDamageByClassGameTable[0] = GameTableReader.Read<GtNpcDamageByClassRecord>("NpcDamageByClass.txt");
|
||||
NpcDamageByClassGameTable[1] = GameTableReader.Read<GtNpcDamageByClassRecord>("NpcDamageByClassExp1.txt");
|
||||
@@ -355,6 +362,7 @@ namespace Game.DataStorage
|
||||
NpcDamageByClassGameTable[4] = GameTableReader.Read<GtNpcDamageByClassRecord>("NpcDamageByClassExp4.txt");
|
||||
NpcDamageByClassGameTable[5] = GameTableReader.Read<GtNpcDamageByClassRecord>("NpcDamageByClassExp5.txt");
|
||||
NpcDamageByClassGameTable[6] = GameTableReader.Read<GtNpcDamageByClassRecord>("NpcDamageByClassExp6.txt");
|
||||
NpcDamageByClassGameTable[7] = GameTableReader.Read<GtNpcDamageByClassRecord>("NpcDamageByClassExp7.txt");
|
||||
NpcManaCostScalerGameTable = GameTableReader.Read<GtNpcManaCostScalerRecord>("NPCManaCostScaler.txt");
|
||||
NpcTotalHpGameTable[0] = GameTableReader.Read<GtNpcTotalHpRecord>("NpcTotalHp.txt");
|
||||
NpcTotalHpGameTable[1] = GameTableReader.Read<GtNpcTotalHpRecord>("NpcTotalHpExp1.txt");
|
||||
@@ -363,6 +371,7 @@ namespace Game.DataStorage
|
||||
NpcTotalHpGameTable[4] = GameTableReader.Read<GtNpcTotalHpRecord>("NpcTotalHpExp4.txt");
|
||||
NpcTotalHpGameTable[5] = GameTableReader.Read<GtNpcTotalHpRecord>("NpcTotalHpExp5.txt");
|
||||
NpcTotalHpGameTable[6] = GameTableReader.Read<GtNpcTotalHpRecord>("NpcTotalHpExp6.txt");
|
||||
NpcTotalHpGameTable[7] = GameTableReader.Read<GtNpcTotalHpRecord>("NpcTotalHpExp7.txt");
|
||||
SpellScalingGameTable = GameTableReader.Read<GtSpellScalingRecord>("SpellScaling.txt");
|
||||
XpGameTable = GameTableReader.Read<GtXpRecord>("xp.txt");
|
||||
|
||||
@@ -371,6 +380,7 @@ namespace Game.DataStorage
|
||||
|
||||
#region Main Collections
|
||||
public static DB6Storage<AchievementRecord> AchievementStorage;
|
||||
public static DB6Storage<AnimationDataRecord> AnimationDataStorage;
|
||||
public static DB6Storage<AnimKitRecord> AnimKitStorage;
|
||||
public static DB6Storage<AreaGroupMemberRecord> AreaGroupMemberStorage;
|
||||
public static DB6Storage<AreaTableRecord> AreaTableStorage;
|
||||
@@ -409,6 +419,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<ChrSpecializationRecord> ChrSpecializationStorage;
|
||||
public static DB6Storage<CinematicCameraRecord> CinematicCameraStorage;
|
||||
public static DB6Storage<CinematicSequencesRecord> CinematicSequencesStorage;
|
||||
public static DB6Storage<ContentTuningRecord> ContentTuningStorage;
|
||||
public static DB6Storage<ConversationLineRecord> ConversationLineStorage;
|
||||
public static DB6Storage<CreatureDisplayInfoRecord> CreatureDisplayInfoStorage;
|
||||
public static DB6Storage<CreatureDisplayInfoExtraRecord> CreatureDisplayInfoExtraStorage;
|
||||
@@ -428,6 +439,8 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<EmotesRecord> EmotesStorage;
|
||||
public static DB6Storage<EmotesTextRecord> EmotesTextStorage;
|
||||
public static DB6Storage<EmotesTextSoundRecord> EmotesTextSoundStorage;
|
||||
public static DB6Storage<ExpectedStatRecord> ExpectedStatStorage;
|
||||
public static DB6Storage<ExpectedStatModRecord> ExpectedStatModStorage;
|
||||
public static DB6Storage<FactionRecord> FactionStorage;
|
||||
public static DB6Storage<FactionTemplateRecord> FactionTemplateStorage;
|
||||
public static DB6Storage<GameObjectsRecord> GameObjectsStorage;
|
||||
@@ -512,6 +525,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<NamesProfanityRecord> NamesProfanityStorage;
|
||||
public static DB6Storage<NamesReservedRecord> NamesReservedStorage;
|
||||
public static DB6Storage<NamesReservedLocaleRecord> NamesReservedLocaleStorage;
|
||||
public static DB6Storage<NumTalentsAtLevelRecord> NumTalentsAtLevelStorage;
|
||||
public static DB6Storage<OverrideSpellDataRecord> OverrideSpellDataStorage;
|
||||
public static DB6Storage<PhaseRecord> PhaseStorage;
|
||||
public static DB6Storage<PhaseXPhaseGroupRecord> PhaseXPhaseGroupStorage;
|
||||
@@ -521,9 +535,9 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<PrestigeLevelInfoRecord> PrestigeLevelInfoStorage;
|
||||
public static DB6Storage<PvpDifficultyRecord> PvpDifficultyStorage;
|
||||
public static DB6Storage<PvpItemRecord> PvpItemStorage;
|
||||
public static DB6Storage<PvpRewardRecord> PvpRewardStorage;
|
||||
public static DB6Storage<PvpTalentRecord> PvpTalentStorage;
|
||||
public static DB6Storage<PvpTalentUnlockRecord> PvpTalentUnlockStorage;
|
||||
public static DB6Storage<PvpTalentCategoryRecord> PvpTalentCategoryStorage;
|
||||
public static DB6Storage<PvpTalentSlotUnlockRecord> PvpTalentSlotUnlockStorage;
|
||||
public static DB6Storage<QuestFactionRewardRecord> QuestFactionRewardStorage;
|
||||
public static DB6Storage<QuestMoneyRewardRecord> QuestMoneyRewardStorage;
|
||||
public static DB6Storage<QuestPackageItemRecord> QuestPackageItemStorage;
|
||||
@@ -535,7 +549,6 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<RewardPackXCurrencyTypeRecord> RewardPackXCurrencyTypeStorage;
|
||||
public static DB6Storage<RewardPackXItemRecord> RewardPackXItemStorage;
|
||||
public static DB6Storage<RulesetItemUpgradeRecord> RulesetItemUpgradeStorage;
|
||||
public static DB6Storage<SandboxScalingRecord> SandboxScalingStorage;
|
||||
public static DB6Storage<ScalingStatDistributionRecord> ScalingStatDistributionStorage;
|
||||
public static DB6Storage<ScenarioRecord> ScenarioStorage;
|
||||
public static DB6Storage<ScenarioStepRecord> ScenarioStepStorage;
|
||||
@@ -548,7 +561,6 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<SkillRaceClassInfoRecord> SkillRaceClassInfoStorage;
|
||||
public static DB6Storage<SoundKitRecord> SoundKitStorage;
|
||||
public static DB6Storage<SpecializationSpellsRecord> SpecializationSpellsStorage;
|
||||
public static DB6Storage<SpellRecord> SpellStorage;
|
||||
public static DB6Storage<SpellAuraOptionsRecord> SpellAuraOptionsStorage;
|
||||
public static DB6Storage<SpellAuraRestrictionsRecord> SpellAuraRestrictionsStorage;
|
||||
public static DB6Storage<SpellCastTimesRecord> SpellCastTimesStorage;
|
||||
@@ -567,6 +579,7 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<SpellLearnSpellRecord> SpellLearnSpellStorage;
|
||||
public static DB6Storage<SpellLevelsRecord> SpellLevelsStorage;
|
||||
public static DB6Storage<SpellMiscRecord> SpellMiscStorage;
|
||||
public static DB6Storage<SpellNameRecord> SpellNameStorage;
|
||||
public static DB6Storage<SpellPowerRecord> SpellPowerStorage;
|
||||
public static DB6Storage<SpellPowerDifficultyRecord> SpellPowerDifficultyStorage;
|
||||
public static DB6Storage<SpellProcsPerMinuteRecord> SpellProcsPerMinuteStorage;
|
||||
@@ -594,14 +607,16 @@ namespace Game.DataStorage
|
||||
public static DB6Storage<TransmogSetItemRecord> TransmogSetItemStorage;
|
||||
public static DB6Storage<TransportAnimationRecord> TransportAnimationStorage;
|
||||
public static DB6Storage<TransportRotationRecord> TransportRotationStorage;
|
||||
public static DB6Storage<UiMapRecord> UiMapStorage;
|
||||
public static DB6Storage<UiMapAssignmentRecord> UiMapAssignmentStorage;
|
||||
public static DB6Storage<UiMapLinkRecord> UiMapLinkStorage;
|
||||
public static DB6Storage<UiMapXMapArtRecord> UiMapXMapArtStorage;
|
||||
public static DB6Storage<UnitPowerBarRecord> UnitPowerBarStorage;
|
||||
public static DB6Storage<VehicleRecord> VehicleStorage;
|
||||
public static DB6Storage<VehicleSeatRecord> VehicleSeatStorage;
|
||||
public static DB6Storage<WMOAreaTableRecord> WMOAreaTableStorage;
|
||||
public static DB6Storage<WorldEffectRecord> WorldEffectStorage;
|
||||
public static DB6Storage<WorldMapAreaRecord> WorldMapAreaStorage;
|
||||
public static DB6Storage<WorldMapOverlayRecord> WorldMapOverlayStorage;
|
||||
public static DB6Storage<WorldMapTransformsRecord> WorldMapTransformsStorage;
|
||||
public static DB6Storage<WorldSafeLocsRecord> WorldSafeLocsStorage;
|
||||
#endregion
|
||||
|
||||
@@ -613,7 +628,6 @@ namespace Game.DataStorage
|
||||
public static GameTable<GtBaseMPRecord> BaseMPGameTable;
|
||||
public static GameTable<GtCombatRatingsRecord> CombatRatingsGameTable;
|
||||
public static GameTable<GtCombatRatingsMultByILvlRecord> CombatRatingsMultByILvlGameTable;
|
||||
public static GameTable<GtHonorLevelRecord> HonorLevelGameTable;
|
||||
public static GameTable<GtHpPerStaRecord> HpPerStaGameTable;
|
||||
public static GameTable<GtItemSocketCostPerLevelRecord> ItemSocketCostPerLevelGameTable;
|
||||
public static GameTable<GtNpcDamageByClassRecord>[] NpcDamageByClassGameTable = new GameTable<GtNpcDamageByClassRecord>[(int)Expansion.Max];
|
||||
@@ -697,6 +711,7 @@ namespace Game.DataStorage
|
||||
case (int)Class.DemonHunter:
|
||||
return row.DemonHunter;
|
||||
case -1:
|
||||
case -7:
|
||||
return row.Item;
|
||||
case -2:
|
||||
return row.Consumable;
|
||||
@@ -708,6 +723,8 @@ namespace Game.DataStorage
|
||||
return row.Gem3;
|
||||
case -6:
|
||||
return row.Health;
|
||||
case -8:
|
||||
return row.DamageReplaceStat;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Game.DataStorage
|
||||
int arrayLength = ColumnMeta[dataFieldIndex].ArraySize;
|
||||
if (arrayLength > 1)
|
||||
{
|
||||
for (var arrayIndex = 0; arrayIndex < arrayLength; ++arrayIndex)
|
||||
while (arrayLength > 0)
|
||||
{
|
||||
var fieldInfo = fieldsInfo[objectFieldIndex++];
|
||||
if (fieldInfo.IsArray)
|
||||
@@ -155,7 +155,6 @@ namespace Game.DataStorage
|
||||
StringTable = null;
|
||||
FieldStructure = null;
|
||||
ColumnMeta = null;
|
||||
RelationShipData = null;
|
||||
}
|
||||
|
||||
static void ReadHeader(BinaryReader reader)
|
||||
@@ -172,137 +171,49 @@ namespace Game.DataStorage
|
||||
Header.MinId = reader.ReadInt32();
|
||||
Header.MaxId = reader.ReadInt32();
|
||||
Header.Locale = reader.ReadInt32();
|
||||
Header.CopyTableSize = reader.ReadInt32();
|
||||
Header.Flags = (HeaderFlags)reader.ReadUInt16();
|
||||
Header.IdIndex = reader.ReadUInt16();
|
||||
Header.TotalFieldCount = reader.ReadUInt32();
|
||||
|
||||
Header.BitpackedDataOffset = reader.ReadUInt32();
|
||||
Header.LookupColumnCount = reader.ReadUInt32();
|
||||
Header.OffsetTableOffset = reader.ReadUInt32();
|
||||
Header.IdListSize = reader.ReadUInt32();
|
||||
Header.ColumnMetaSize = reader.ReadUInt32();
|
||||
Header.CommonDataSize = reader.ReadUInt32();
|
||||
Header.PalletDataSize = reader.ReadUInt32();
|
||||
Header.RelationshipDataSize = reader.ReadUInt32();
|
||||
|
||||
//Gather field structures
|
||||
FieldStructure = new List<FieldStructureEntry>();
|
||||
for (int i = 0; i < Header.FieldCount; i++)
|
||||
{
|
||||
var field = new FieldStructureEntry(reader.ReadInt16(), reader.ReadUInt16());
|
||||
FieldStructure.Add(field);
|
||||
}
|
||||
Header.SectionsCount = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
static Dictionary<int, byte[]> ReadData(BinaryReader reader)
|
||||
{
|
||||
Dictionary<int, byte[]> CopyTable = new Dictionary<int, byte[]>();
|
||||
List<Tuple<int, short>> offsetmap = new List<Tuple<int, short>>();
|
||||
Dictionary<int, OffsetDuplicate> firstindex = new Dictionary<int, OffsetDuplicate>();
|
||||
Dictionary<int, int> OffsetDuplicates = new Dictionary<int, int>();
|
||||
Dictionary<int, List<int>> Copies = new Dictionary<int, List<int>>();
|
||||
Dictionary<int, byte[]> records = new Dictionary<int, byte[]>();
|
||||
|
||||
bool hasOffsetTable = Header.HasOffsetTable();
|
||||
bool hasIndexTable = Header.HasIndexTable();
|
||||
var sections = reader.ReadArray<SectionHeader>(Header.SectionsCount);
|
||||
|
||||
byte[] recordData;
|
||||
if (hasOffsetTable)
|
||||
recordData = reader.ReadBytes((int)(Header.OffsetTableOffset - 84 - 4 * Header.FieldCount));
|
||||
else
|
||||
{
|
||||
recordData = reader.ReadBytes((int)(Header.RecordCount * Header.RecordSize));
|
||||
Array.Resize(ref recordData, recordData.Length + 8);
|
||||
}
|
||||
//Gather field structures
|
||||
FieldStructure = reader.ReadArray<FieldMetaData>(Header.FieldCount);
|
||||
|
||||
if (Header.StringTableSize != 0)
|
||||
{
|
||||
// string data
|
||||
StringTable = new Dictionary<int, string>();
|
||||
|
||||
for (int i = 0; i < Header.StringTableSize;)
|
||||
{
|
||||
long oldPos = reader.BaseStream.Position;
|
||||
|
||||
StringTable[i] = reader.ReadCString();
|
||||
|
||||
i += (int)(reader.BaseStream.Position - oldPos);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int[] m_indexes = null;
|
||||
|
||||
// OffsetTable
|
||||
if (hasOffsetTable && Header.OffsetTableOffset > 0)
|
||||
{
|
||||
reader.BaseStream.Position = Header.OffsetTableOffset;
|
||||
for (int i = 0; i < (Header.MaxId - Header.MinId + 1); i++)
|
||||
{
|
||||
int offset = reader.ReadInt32();
|
||||
short length = reader.ReadInt16();
|
||||
|
||||
if (offset == 0 || length == 0)
|
||||
continue;
|
||||
|
||||
// special case, may contain duplicates in the offset map that we don't want
|
||||
if (Header.CopyTableSize == 0)
|
||||
{
|
||||
if (!firstindex.ContainsKey(offset))
|
||||
firstindex.Add(offset, new OffsetDuplicate(offsetmap.Count, firstindex.Count));
|
||||
else
|
||||
OffsetDuplicates.Add(Header.MinId + i, firstindex[offset].VisibleIndex);
|
||||
}
|
||||
|
||||
offsetmap.Add(new Tuple<int, short>(offset, length));
|
||||
}
|
||||
}
|
||||
|
||||
// IndexTable
|
||||
if (hasIndexTable)
|
||||
m_indexes = reader.ReadArray<int>(Header.RecordCount);
|
||||
|
||||
// Copytable
|
||||
if (Header.CopyTableSize > 0)
|
||||
{
|
||||
long end = reader.BaseStream.Position + Header.CopyTableSize;
|
||||
while (reader.BaseStream.Position < end)
|
||||
{
|
||||
int id = reader.ReadInt32();
|
||||
int idcopy = reader.ReadInt32();
|
||||
|
||||
if (!Copies.ContainsKey(idcopy))
|
||||
Copies.Add(idcopy, new List<int>());
|
||||
|
||||
Copies[idcopy].Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
// ColumnMeta
|
||||
// column meta data
|
||||
ColumnMeta = new List<ColumnStructureEntry>();
|
||||
if (Header.ColumnMetaSize != 0)
|
||||
for (int i = 0; i < Header.FieldCount; i++)
|
||||
{
|
||||
for (int i = 0; i < Header.FieldCount; i++)
|
||||
var column = new ColumnStructureEntry()
|
||||
{
|
||||
var column = new ColumnStructureEntry()
|
||||
{
|
||||
RecordOffset = reader.ReadUInt16(),
|
||||
Size = reader.ReadUInt16(),
|
||||
AdditionalDataSize = reader.ReadUInt32(), // size of pallet / sparse values
|
||||
CompressionType = (DB2ColumnCompression)reader.ReadUInt32(),
|
||||
BitOffset = reader.ReadInt32(),
|
||||
BitWidth = reader.ReadInt32(),
|
||||
Cardinality = reader.ReadInt32()
|
||||
};
|
||||
RecordOffset = reader.ReadUInt16(),
|
||||
Size = reader.ReadUInt16(),
|
||||
AdditionalDataSize = reader.ReadUInt32(), // size of pallet / sparse values
|
||||
CompressionType = (DB2ColumnCompression)reader.ReadUInt32(),
|
||||
BitOffset = reader.ReadInt32(),
|
||||
BitWidth = reader.ReadInt32(),
|
||||
Cardinality = reader.ReadInt32()
|
||||
};
|
||||
|
||||
// preload arraysizes
|
||||
if (column.CompressionType == DB2ColumnCompression.None)
|
||||
column.ArraySize = Math.Max(column.Size / FieldStructure[i].BitCount, 1);
|
||||
else if (column.CompressionType == DB2ColumnCompression.PalletArray)
|
||||
column.ArraySize = Math.Max(column.Cardinality, 1);
|
||||
// preload arraysizes
|
||||
if (column.CompressionType == DB2ColumnCompression.None)
|
||||
column.ArraySize = Math.Max(column.Size / FieldStructure[i].BitCount, 1);
|
||||
else if (column.CompressionType == DB2ColumnCompression.PalletArray)
|
||||
column.ArraySize = Math.Max(column.Cardinality, 1);
|
||||
|
||||
ColumnMeta.Add(column);
|
||||
}
|
||||
ColumnMeta.Add(column);
|
||||
}
|
||||
|
||||
// Pallet values
|
||||
@@ -330,148 +241,194 @@ namespace Game.DataStorage
|
||||
}
|
||||
}
|
||||
|
||||
// Relationships
|
||||
if (Header.RelationshipDataSize > 0)
|
||||
{
|
||||
RelationShipData = new RelationShipData()
|
||||
{
|
||||
Records = reader.ReadUInt32(),
|
||||
MinId = reader.ReadUInt32(),
|
||||
MaxId = reader.ReadUInt32(),
|
||||
Entries = new Dictionary<uint, byte[]>()
|
||||
};
|
||||
List<Tuple<int, int>> offsetmap = new List<Tuple<int, int>>();
|
||||
|
||||
for (int i = 0; i < RelationShipData.Records; i++)
|
||||
{
|
||||
byte[] foreignKey = reader.ReadBytes(4);
|
||||
uint index = reader.ReadUInt32();
|
||||
// has duplicates just like the copy table does... why?
|
||||
if (!RelationShipData.Entries.ContainsKey(index))
|
||||
RelationShipData.Entries.Add(index, foreignKey);
|
||||
bool hasIndexTable = Header.HasIndexTable();
|
||||
|
||||
byte[] recordData;
|
||||
for (int sectionIndex = 0; sectionIndex < Header.SectionsCount; sectionIndex++)
|
||||
{
|
||||
reader.BaseStream.Position = sections[sectionIndex].FileOffset;
|
||||
|
||||
if (Header.HasOffsetTable())
|
||||
{
|
||||
// sparse data with inlined strings
|
||||
recordData = reader.ReadBytes(sections[sectionIndex].SparseTableOffset - sections[sectionIndex].FileOffset);
|
||||
|
||||
// OffsetTable
|
||||
for (int i = 0; i < (Header.MaxId - Header.MinId + 1); i++)
|
||||
{
|
||||
int offset = reader.ReadInt32();
|
||||
int length = reader.ReadInt32();
|
||||
|
||||
offsetmap.Add(new Tuple<int, int>(offset, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record Data
|
||||
for (int i = 0; i < Header.RecordCount; i++)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
if (hasOffsetTable && hasIndexTable)
|
||||
else
|
||||
{
|
||||
id = m_indexes[CopyTable.Count];
|
||||
var map = offsetmap[i];
|
||||
// records data
|
||||
recordData = reader.ReadBytes((int)(sections[sectionIndex].NumRecords * Header.RecordSize));
|
||||
|
||||
if (Header.CopyTableSize == 0 && firstindex[map.Item1].HiddenIndex != i) // ignore duplicates
|
||||
continue;
|
||||
Array.Resize(ref recordData, recordData.Length + 8); // pad with extra zeros so we don't crash when reading
|
||||
|
||||
reader.BaseStream.Position = map.Item1;
|
||||
// string data
|
||||
StringTable = new Dictionary<int, string>();
|
||||
|
||||
byte[] data = reader.ReadBytes(map.Item2);
|
||||
|
||||
IEnumerable<byte> recordbytes = data;
|
||||
|
||||
// append relationship id
|
||||
if (RelationShipData != null)
|
||||
for (int i = 0; i < sections[sectionIndex].StringTableSize;)
|
||||
{
|
||||
// seen cases of missing indicies
|
||||
if (RelationShipData.Entries.TryGetValue((uint)i, out byte[] foreignData))
|
||||
recordbytes = recordbytes.Concat(foreignData);
|
||||
else
|
||||
recordbytes = recordbytes.Concat(new byte[4]);
|
||||
int oldPos = (int)reader.BaseStream.Position;
|
||||
|
||||
StringTable[i] = reader.ReadCString();
|
||||
|
||||
i += (int)(reader.BaseStream.Position - oldPos);
|
||||
}
|
||||
}
|
||||
|
||||
CopyTable.Add(id, recordbytes.ToArray());
|
||||
// IndexTable
|
||||
int[] m_indexes = reader.ReadArray<int>((uint)(sections[sectionIndex].IndexDataSize / 4));
|
||||
|
||||
if (Copies.ContainsKey(id))
|
||||
// duplicate rows data
|
||||
Dictionary<int, int> copyData = new Dictionary<int, int>();
|
||||
|
||||
for (int i = 0; i < sections[sectionIndex].CopyTableSize / 8; i++)
|
||||
copyData[reader.ReadInt32()] = reader.ReadInt32();
|
||||
|
||||
// Relationships
|
||||
RelationShipData relationShipData = null;
|
||||
if (sections[sectionIndex].ParentLookupDataSize > 0)
|
||||
{
|
||||
relationShipData = new RelationShipData()
|
||||
{
|
||||
foreach (int copy in Copies[id])
|
||||
CopyTable.Add(copy, data.ToArray());
|
||||
Records = reader.ReadUInt32(),
|
||||
MinId = reader.ReadUInt32(),
|
||||
MaxId = reader.ReadUInt32(),
|
||||
Entries = new Dictionary<uint, byte[]>()
|
||||
};
|
||||
|
||||
for (int i = 0; i < relationShipData.Records; i++)
|
||||
{
|
||||
byte[] foreignKey = reader.ReadBytes(4);
|
||||
uint index = reader.ReadUInt32();
|
||||
// has duplicates just like the copy table does... why?
|
||||
if (!relationShipData.Entries.ContainsKey(index))
|
||||
relationShipData.Entries.Add(index, foreignKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Record Data
|
||||
if (Header.HasOffsetTable() && hasIndexTable)
|
||||
{
|
||||
for (int i = 0; i < Header.RecordCount; ++i)
|
||||
{
|
||||
int id = m_indexes[records.Count];
|
||||
var map = offsetmap[i];
|
||||
|
||||
reader.BaseStream.Position = map.Item1;
|
||||
|
||||
byte[] data = reader.ReadBytes(map.Item2);
|
||||
|
||||
IEnumerable<byte> recordbytes = data;
|
||||
|
||||
// append relationship id
|
||||
if (relationShipData != null)
|
||||
{
|
||||
// seen cases of missing indicies
|
||||
if (relationShipData.Entries.TryGetValue((uint)i, out byte[] foreignData))
|
||||
recordbytes = recordbytes.Concat(foreignData);
|
||||
else
|
||||
recordbytes = recordbytes.Concat(new byte[4]);
|
||||
}
|
||||
|
||||
records.Add(id, recordbytes.ToArray());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitReader bitReader = new BitReader(recordData);
|
||||
bitReader.Offset = i * (int)Header.RecordSize;
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BinaryWriter binaryWriter = new BinaryWriter(stream);
|
||||
|
||||
if (hasIndexTable)
|
||||
id = m_indexes[i];
|
||||
|
||||
for (int f = 0; f < Header.FieldCount; f++)
|
||||
for (int i = 0; i < Header.RecordCount; ++i)
|
||||
{
|
||||
int bitWidth = ColumnMeta[f].BitWidth;
|
||||
bitReader.Position = 0;
|
||||
bitReader.Offset = i * (int)Header.RecordSize;
|
||||
|
||||
switch (ColumnMeta[f].CompressionType)
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BinaryWriter binaryWriter = new BinaryWriter(stream);
|
||||
|
||||
int id = 0;
|
||||
if (sections[sectionIndex].IndexDataSize != 0)
|
||||
id = m_indexes[i];
|
||||
|
||||
for (int f = 0; f < Header.FieldCount; f++)
|
||||
{
|
||||
case DB2ColumnCompression.None:
|
||||
int bitSize = FieldStructure[f].BitCount;
|
||||
if (!hasIndexTable && f == Header.IdIndex)
|
||||
{
|
||||
id = (int)bitReader.ReadUInt32(bitSize);// always read Ids as ints
|
||||
binaryWriter.Write(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int x = 0; x < ColumnMeta[f].ArraySize; x++)
|
||||
binaryWriter.Write(bitReader.ReadValue(bitSize));
|
||||
}
|
||||
break;
|
||||
int bitWidth = ColumnMeta[f].BitWidth;
|
||||
|
||||
case DB2ColumnCompression.Immediate:
|
||||
if (!hasIndexTable && f == Header.IdIndex)
|
||||
{
|
||||
id = (int)bitReader.ReadUInt32(bitWidth);// always read Ids as ints
|
||||
binaryWriter.Write(id);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
binaryWriter.Write(bitReader.ReadValue(bitWidth, ColumnMeta[f].BitOffset, ColumnMeta[f].Cardinality == 1));
|
||||
break;
|
||||
switch (ColumnMeta[f].CompressionType)
|
||||
{
|
||||
case DB2ColumnCompression.None:
|
||||
int bitSize = FieldStructure[f].BitCount;
|
||||
if (!hasIndexTable && f == Header.IdIndex)
|
||||
{
|
||||
id = (int)bitReader.ReadUInt32(bitSize);// always read Ids as ints
|
||||
binaryWriter.Write(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int x = 0; x < ColumnMeta[f].ArraySize; x++)
|
||||
binaryWriter.Write(bitReader.ReadValue(bitSize));
|
||||
}
|
||||
break;
|
||||
|
||||
case DB2ColumnCompression.CommonData:
|
||||
if (ColumnMeta[f].SparseValues.TryGetValue(id, out byte[] valBytes))
|
||||
binaryWriter.Write(valBytes);
|
||||
else
|
||||
binaryWriter.Write(ColumnMeta[f].BitOffset);
|
||||
break;
|
||||
case DB2ColumnCompression.Immediate:
|
||||
case DB2ColumnCompression.SignedImmediate:
|
||||
if (!hasIndexTable && f == Header.IdIndex)
|
||||
{
|
||||
id = (int)bitReader.ReadUInt32(bitWidth);// always read Ids as ints
|
||||
binaryWriter.Write(id);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
binaryWriter.Write(bitReader.ReadValue(bitWidth, ColumnMeta[f].BitOffset, ColumnMeta[f].CompressionType == DB2ColumnCompression.SignedImmediate));
|
||||
break;
|
||||
|
||||
case DB2ColumnCompression.Pallet:
|
||||
case DB2ColumnCompression.PalletArray:
|
||||
uint palletIndex = bitReader.ReadUInt32(bitWidth);
|
||||
binaryWriter.Write(ColumnMeta[f].PalletValues[(int)palletIndex]);
|
||||
break;
|
||||
case DB2ColumnCompression.CommonData:
|
||||
if (ColumnMeta[f].SparseValues.TryGetValue(id, out byte[] valBytes))
|
||||
binaryWriter.Write(valBytes);
|
||||
else
|
||||
binaryWriter.Write(ColumnMeta[f].BitOffset);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception($"Unknown compression {ColumnMeta[f].CompressionType}");
|
||||
case DB2ColumnCompression.Pallet:
|
||||
case DB2ColumnCompression.PalletArray:
|
||||
uint palletIndex = bitReader.ReadUInt32(bitWidth);
|
||||
binaryWriter.Write(ColumnMeta[f].PalletValues[(int)palletIndex]);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception($"Unknown compression {ColumnMeta[f].CompressionType}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append relationship id
|
||||
if (RelationShipData != null)
|
||||
{
|
||||
// seen cases of missing indicies
|
||||
if (RelationShipData.Entries.TryGetValue((uint)i, out byte[] foreignData))
|
||||
binaryWriter.Write(foreignData);
|
||||
else
|
||||
binaryWriter.Write(0);
|
||||
}
|
||||
|
||||
CopyTable.Add(id, stream.ToArray());
|
||||
|
||||
if (Copies.ContainsKey(id))
|
||||
{
|
||||
foreach (int copy in Copies[id])
|
||||
// append relationship id
|
||||
if (relationShipData != null)
|
||||
{
|
||||
byte[] newrecord = CopyTable[id].ToArray();
|
||||
CopyTable.Add(copy, newrecord);
|
||||
// seen cases of missing indicies
|
||||
if (relationShipData.Entries.TryGetValue((uint)i, out byte[] foreignData))
|
||||
binaryWriter.Write(foreignData);
|
||||
else
|
||||
binaryWriter.Write(0);
|
||||
}
|
||||
|
||||
records.Add(id, stream.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var copyRow in copyData)
|
||||
{
|
||||
byte[] newrecord = records[copyRow.Value].ToArray();
|
||||
records.Add(copyRow.Key, newrecord);
|
||||
}
|
||||
}
|
||||
|
||||
return CopyTable;
|
||||
return records;
|
||||
}
|
||||
|
||||
static Dictionary<Type, int> bytecounts = new Dictionary<Type, int>()
|
||||
@@ -493,13 +450,13 @@ namespace Game.DataStorage
|
||||
return 4 - bytecounts[type];
|
||||
}
|
||||
|
||||
static FieldStructureEntry[] GetBits()
|
||||
static FieldMetaData[] GetBits()
|
||||
{
|
||||
List<FieldStructureEntry> bits = new List<FieldStructureEntry>();
|
||||
List<FieldMetaData> bits = new List<FieldMetaData>();
|
||||
for (int i = 0; i < ColumnMeta.Count; i++)
|
||||
{
|
||||
short bitcount = (short)(FieldStructure[i].BitCount == 64 ? FieldStructure[i].BitCount : 0); // force bitcounts
|
||||
bits.Add(new FieldStructureEntry(bitcount, 0));
|
||||
bits.Add(new FieldMetaData(bitcount, 0));
|
||||
}
|
||||
|
||||
return bits.ToArray();
|
||||
@@ -619,9 +576,8 @@ namespace Game.DataStorage
|
||||
static DB6Header Header;
|
||||
static Dictionary<int, string> StringTable;
|
||||
|
||||
static List<FieldStructureEntry> FieldStructure;
|
||||
static FieldMetaData[] FieldStructure;
|
||||
static List<ColumnStructureEntry> ColumnMeta;
|
||||
static RelationShipData RelationShipData;
|
||||
}
|
||||
|
||||
public struct DB6FieldInfo
|
||||
@@ -680,25 +636,21 @@ namespace Game.DataStorage
|
||||
public int MinId;
|
||||
public int MaxId;
|
||||
public int Locale;
|
||||
public int CopyTableSize;
|
||||
public HeaderFlags Flags;
|
||||
public int IdIndex;
|
||||
public uint TotalFieldCount;
|
||||
public uint BitpackedDataOffset;
|
||||
public uint LookupColumnCount;
|
||||
public uint OffsetTableOffset;
|
||||
public uint IdListSize;
|
||||
public uint ColumnMetaSize;
|
||||
public uint CommonDataSize;
|
||||
public uint PalletDataSize;
|
||||
public uint RelationshipDataSize;
|
||||
public uint SectionsCount;
|
||||
}
|
||||
|
||||
public class FieldStructureEntry
|
||||
public struct FieldMetaData
|
||||
{
|
||||
public short Bits;
|
||||
public ushort Offset;
|
||||
public int Length = 1;
|
||||
|
||||
public int ByteCount
|
||||
{
|
||||
@@ -720,7 +672,7 @@ namespace Game.DataStorage
|
||||
}
|
||||
}
|
||||
|
||||
public FieldStructureEntry(short bits, ushort offset)
|
||||
public FieldMetaData(short bits, ushort offset)
|
||||
{
|
||||
Bits = bits;
|
||||
Offset = offset;
|
||||
@@ -742,6 +694,19 @@ namespace Game.DataStorage
|
||||
public int ArraySize { get; set; } = 1;
|
||||
}
|
||||
|
||||
public struct SectionHeader
|
||||
{
|
||||
public int unk1;
|
||||
public int unk2;
|
||||
public int FileOffset;
|
||||
public int NumRecords;
|
||||
public int StringTableSize;
|
||||
public int CopyTableSize;
|
||||
public int SparseTableOffset; // CatalogDataOffset, absolute value, {uint offset, ushort size}[MaxId - MinId + 1]
|
||||
public int IndexDataSize; // int indexData[IndexDataSize / 4]
|
||||
public int ParentLookupDataSize; // uint NumRecords, uint minId, uint maxId, {uint id, uint index}[NumRecords], questionable usefulness...
|
||||
}
|
||||
|
||||
public class RelationShipData
|
||||
{
|
||||
public uint Records;
|
||||
@@ -790,7 +755,8 @@ namespace Game.DataStorage
|
||||
Immediate,
|
||||
CommonData,
|
||||
Pallet,
|
||||
PalletArray
|
||||
PalletArray,
|
||||
SignedImmediate
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -158,7 +158,7 @@ namespace Game.DataStorage
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 Conversation actors. DB table `conversation_actors` is empty.");
|
||||
}
|
||||
|
||||
SQLResult templateResult = DB.World.Query("SELECT Id, FirstLineId, LastLineEndTime, ScriptName FROM conversation_template");
|
||||
SQLResult templateResult = DB.World.Query("SELECT Id, FirstLineId, LastLineEndTime, TextureKitId, ScriptName FROM conversation_template");
|
||||
if (!templateResult.IsEmpty())
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
@@ -169,6 +169,7 @@ namespace Game.DataStorage
|
||||
conversationTemplate.Id = templateResult.Read<uint>(0);
|
||||
conversationTemplate.FirstLineId = templateResult.Read<uint>(1);
|
||||
conversationTemplate.LastLineEndTime = templateResult.Read<uint>(2);
|
||||
conversationTemplate.TextureKitId = templateResult.Read<uint>(3);
|
||||
conversationTemplate.ScriptId = Global.ObjectMgr.GetScriptId(templateResult.Read<string>(3));
|
||||
|
||||
conversationTemplate.Actors = actorsByConversation[conversationTemplate.Id].ToList();
|
||||
@@ -236,6 +237,7 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public uint FirstLineId; // Link to ConversationLine.db2
|
||||
public uint LastLineEndTime; // Time in ms after conversation creation the last line fades out
|
||||
public uint TextureKitId; // Background texture
|
||||
public uint ScriptId;
|
||||
|
||||
public List<ConversationActorTemplate> Actors = new List<ConversationActorTemplate>();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -156,7 +156,7 @@ namespace Game.DataStorage
|
||||
}
|
||||
}
|
||||
|
||||
FlyByCameraStorage[dbcentry.ID] = cameras;
|
||||
FlyByCameraStorage[dbcentry.Id] = cameras;
|
||||
}
|
||||
|
||||
public static void LoadM2Cameras(string dataPath)
|
||||
|
||||
@@ -23,21 +23,30 @@ namespace Game.DataStorage
|
||||
{
|
||||
public class AchievementRecord
|
||||
{
|
||||
public string Title;
|
||||
public string Description;
|
||||
public string Title;
|
||||
public string Reward;
|
||||
public AchievementFlags Flags;
|
||||
public uint Id;
|
||||
public short InstanceID;
|
||||
public AchievementFaction Faction;
|
||||
public ushort Supercedes;
|
||||
public ushort Category;
|
||||
public ushort UiOrder;
|
||||
public ushort SharesCriteria;
|
||||
public AchievementFaction Faction;
|
||||
public byte Points;
|
||||
public byte MinimumCriteria;
|
||||
public uint Id;
|
||||
public byte Points;
|
||||
public AchievementFlags Flags;
|
||||
public ushort UiOrder;
|
||||
public uint IconFileID;
|
||||
public ushort CriteriaTree;
|
||||
public uint CriteriaTree;
|
||||
public ushort SharesCriteria;
|
||||
}
|
||||
|
||||
public sealed class AnimationDataRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort Fallback;
|
||||
public byte BehaviorTier;
|
||||
public int BehaviorID;
|
||||
public int[] Flags = new int[2];
|
||||
}
|
||||
|
||||
public sealed class AnimKitRecord
|
||||
@@ -60,27 +69,27 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string ZoneName;
|
||||
public LocalizedString AreaName;
|
||||
public AreaFlags[] Flags = new AreaFlags[2];
|
||||
public float AmbientMultiplier;
|
||||
public ushort ContinentID;
|
||||
public ushort ParentAreaID;
|
||||
public short AreaBit;
|
||||
public ushort AmbienceID;
|
||||
public ushort ZoneMusic;
|
||||
public ushort IntroSound;
|
||||
public ushort[] LiquidTypeID = new ushort[4];
|
||||
public ushort UwZoneMusic;
|
||||
public ushort UwAmbience;
|
||||
public ushort PvpCombastWorldStateID;
|
||||
public byte SoundProviderPref;
|
||||
public byte SoundProviderPrefUnderwater;
|
||||
public ushort AmbienceID;
|
||||
public ushort UwAmbience;
|
||||
public ushort ZoneMusic;
|
||||
public ushort UwZoneMusic;
|
||||
public byte ExplorationLevel;
|
||||
public ushort IntroSound;
|
||||
public byte UwIntroSound;
|
||||
public byte FactionGroupMask;
|
||||
public float AmbientMultiplier;
|
||||
public byte MountFlags;
|
||||
public ushort PvpCombastWorldStateID;
|
||||
public byte WildBattlePetLevelMin;
|
||||
public byte WildBattlePetLevelMax;
|
||||
public byte WindSettingsID;
|
||||
public byte UwIntroSound;
|
||||
public AreaFlags[] Flags = new AreaFlags[2];
|
||||
public ushort[] LiquidTypeID = new ushort[4];
|
||||
|
||||
public bool IsSanctuary()
|
||||
{
|
||||
@@ -94,20 +103,20 @@ namespace Game.DataStorage
|
||||
public sealed class AreaTriggerRecord
|
||||
{
|
||||
public Vector3 Pos;
|
||||
public uint Id;
|
||||
public ushort ContinentID;
|
||||
public sbyte PhaseUseFlags;
|
||||
public ushort PhaseID;
|
||||
public ushort PhaseGroupID;
|
||||
public float Radius;
|
||||
public float BoxLength;
|
||||
public float BoxWidth;
|
||||
public float BoxHeight;
|
||||
public float BoxYaw;
|
||||
public ushort ContinentID;
|
||||
public ushort PhaseID;
|
||||
public ushort PhaseGroupID;
|
||||
public ushort ShapeID;
|
||||
public ushort AreaTriggerActionSetID;
|
||||
public byte PhaseUseFlags;
|
||||
public byte ShapeType;
|
||||
public byte Flags;
|
||||
public uint Id;
|
||||
public sbyte ShapeType;
|
||||
public short ShapeID;
|
||||
public short AreaTriggerActionSetID;
|
||||
public sbyte Flags;
|
||||
}
|
||||
|
||||
public sealed class ArmorLocationRecord
|
||||
@@ -122,67 +131,67 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class ArtifactRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public uint UiBarOverlayColor;
|
||||
public uint UiBarBackgroundColor;
|
||||
public uint UiNameColor;
|
||||
public uint Id;
|
||||
public ushort UiTextureKitID;
|
||||
public int UiNameColor;
|
||||
public int UiBarOverlayColor;
|
||||
public int UiBarBackgroundColor;
|
||||
public ushort ChrSpecializationID;
|
||||
public byte ArtifactCategoryID;
|
||||
public byte Flags;
|
||||
public byte UiModelSceneID;
|
||||
public byte ArtifactCategoryID;
|
||||
public uint UiModelSceneID;
|
||||
public uint SpellVisualKitID;
|
||||
}
|
||||
|
||||
public sealed class ArtifactAppearanceRecord
|
||||
{
|
||||
public string Name;
|
||||
public uint UiSwatchColor;
|
||||
public uint Id;
|
||||
public ushort ArtifactAppearanceSetID;
|
||||
public byte DisplayIndex;
|
||||
public uint UnlockPlayerConditionID;
|
||||
public byte ItemAppearanceModifierID;
|
||||
public int UiSwatchColor;
|
||||
public float UiModelSaturation;
|
||||
public float UiModelOpacity;
|
||||
public uint OverrideShapeshiftDisplayID;
|
||||
public ushort ArtifactAppearanceSetID;
|
||||
public ushort UiCameraID;
|
||||
public byte DisplayIndex;
|
||||
public byte ItemAppearanceModifierID;
|
||||
public byte Flags;
|
||||
public byte OverrideShapeshiftFormID;
|
||||
public uint Id;
|
||||
public ushort UnlockPlayerConditionID;
|
||||
public byte UiItemAppearanceID;
|
||||
public byte UiAltItemAppearanceID;
|
||||
public uint OverrideShapeshiftDisplayID;
|
||||
public uint UiItemAppearanceID;
|
||||
public uint UiAltItemAppearanceID;
|
||||
public byte Flags;
|
||||
public ushort UiCameraID;
|
||||
}
|
||||
|
||||
public sealed class ArtifactAppearanceSetRecord
|
||||
{
|
||||
public string Name;
|
||||
public string Description;
|
||||
public uint Id;
|
||||
public byte DisplayIndex;
|
||||
public ushort UiCameraID;
|
||||
public ushort AltHandUICameraID;
|
||||
public byte DisplayIndex;
|
||||
public byte ForgeAttachmentOverride;
|
||||
public sbyte ForgeAttachmentOverride;
|
||||
public byte Flags;
|
||||
public uint Id;
|
||||
public uint ArtifactID;
|
||||
public byte ArtifactID;
|
||||
}
|
||||
|
||||
public sealed class ArtifactCategoryRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort XpMultCurrencyID;
|
||||
public ushort XpMultCurveID;
|
||||
public short XpMultCurrencyID;
|
||||
public short XpMultCurveID;
|
||||
}
|
||||
|
||||
public sealed class ArtifactPowerRecord
|
||||
{
|
||||
public Vector2 Pos;
|
||||
public byte ArtifactID;
|
||||
public ArtifactPowerFlag Flags;
|
||||
public byte MaxPurchasableRank;
|
||||
public byte Tier;
|
||||
public Vector2 DisplayPos;
|
||||
public uint Id;
|
||||
public byte Label;
|
||||
public byte ArtifactID;
|
||||
public byte MaxPurchasableRank;
|
||||
public int Label;
|
||||
public ArtifactPowerFlag Flags;
|
||||
public byte Tier;
|
||||
}
|
||||
|
||||
public sealed class ArtifactPowerLinkRecord
|
||||
@@ -195,17 +204,17 @@ namespace Game.DataStorage
|
||||
public sealed class ArtifactPowerPickerRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort PlayerConditionID;
|
||||
public uint PlayerConditionID;
|
||||
}
|
||||
|
||||
public sealed class ArtifactPowerRankRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public float AuraPointsOverride;
|
||||
public ushort ItemBonusListID;
|
||||
public byte RankIndex;
|
||||
public uint ArtifactPowerID;
|
||||
public uint SpellID;
|
||||
public ushort ItemBonusListID;
|
||||
public float AuraPointsOverride;
|
||||
public ushort ArtifactPowerID;
|
||||
}
|
||||
|
||||
public sealed class ArtifactQuestXPRecord
|
||||
@@ -214,31 +223,31 @@ namespace Game.DataStorage
|
||||
public uint[] Difficulty = new uint[10];
|
||||
}
|
||||
|
||||
public class ArtifactTierRecord
|
||||
public sealed class ArtifactTierRecord
|
||||
{
|
||||
public uint ID;
|
||||
public byte ArtifactTier;
|
||||
public byte MaxNumTraits;
|
||||
public byte MaxArtifactKnowledge;
|
||||
public byte KnowledgePlayerCondition;
|
||||
public byte MinimumEmpowerKnowledge;
|
||||
public uint Id;
|
||||
public uint ArtifactTier;
|
||||
public uint MaxNumTraits;
|
||||
public uint MaxArtifactKnowledge;
|
||||
public uint KnowledgePlayerCondition;
|
||||
public uint MinimumEmpowerKnowledge;
|
||||
}
|
||||
|
||||
public class ArtifactUnlockRecord
|
||||
public sealed class ArtifactUnlockRecord
|
||||
{
|
||||
public uint ID;
|
||||
public ushort ItemBonusListID;
|
||||
public byte PowerRank;
|
||||
public uint Id;
|
||||
public uint PowerID;
|
||||
public ushort PlayerConditionID;
|
||||
public uint ArtifactID;
|
||||
public byte PowerRank;
|
||||
public ushort ItemBonusListID;
|
||||
public uint PlayerConditionID;
|
||||
public byte ArtifactID;
|
||||
}
|
||||
|
||||
public sealed class AuctionHouseRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public ushort FactionID;
|
||||
public ushort FactionID; // id of faction.dbc for player factions associated with city
|
||||
public byte DepositRate;
|
||||
public byte ConsignmentRate;
|
||||
}
|
||||
|
||||
@@ -23,24 +23,24 @@ namespace Game.DataStorage
|
||||
public uint Cost;
|
||||
}
|
||||
|
||||
public sealed class BannedAddOnsRecord
|
||||
public sealed class BannedAddonsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string Version;
|
||||
public byte[] Flags = new byte[4];
|
||||
public byte Flags;
|
||||
}
|
||||
|
||||
public sealed class BarberShopStyleRecord
|
||||
{
|
||||
public string DisplayName;
|
||||
public string Description;
|
||||
public uint Id;
|
||||
public byte Type; // value 0 -> hair, value 2 -> facialhair
|
||||
public float CostModifier;
|
||||
public byte Type;
|
||||
public byte Race;
|
||||
public byte Sex;
|
||||
public byte Data;
|
||||
public uint Id;
|
||||
public byte Data; // real ID to hair/facial hair
|
||||
}
|
||||
|
||||
public sealed class BattlePetBreedQualityRecord
|
||||
@@ -53,32 +53,32 @@ namespace Game.DataStorage
|
||||
public sealed class BattlePetBreedStateRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort Value;
|
||||
public byte BattlePetStateID;
|
||||
public uint BattlePetBreedID;
|
||||
public ushort Value;
|
||||
public byte BattlePetBreedID;
|
||||
}
|
||||
|
||||
public sealed class BattlePetSpeciesRecord
|
||||
{
|
||||
public string SourceText;
|
||||
public string Description;
|
||||
public uint CreatureID;
|
||||
public uint IconFileDataID;
|
||||
public uint SummonSpellID;
|
||||
public ushort Flags;
|
||||
public byte PetTypeEnum;
|
||||
public sbyte SourceTypeEnum;
|
||||
public string SourceText;
|
||||
public uint Id;
|
||||
public byte CardUIModelSceneID;
|
||||
public byte LoadoutUIModelSceneID;
|
||||
public uint CreatureID;
|
||||
public uint SummonSpellID;
|
||||
public int IconFileDataID;
|
||||
public byte PetTypeEnum;
|
||||
public ushort Flags;
|
||||
public sbyte SourceTypeEnum;
|
||||
public int CardUIModelSceneID;
|
||||
public int LoadoutUIModelSceneID;
|
||||
}
|
||||
|
||||
public sealed class BattlePetSpeciesStateRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int Value;
|
||||
public byte BattlePetStateID;
|
||||
public uint BattlePetSpeciesID;
|
||||
public int Value;
|
||||
public ushort BattlePetSpeciesID;
|
||||
}
|
||||
|
||||
public sealed class BattlemasterListRecord
|
||||
@@ -88,32 +88,33 @@ namespace Game.DataStorage
|
||||
public string GameType;
|
||||
public string ShortDescription;
|
||||
public string LongDescription;
|
||||
public int IconFileDataID;
|
||||
public short[] MapId = new short[16];
|
||||
public sbyte InstanceType;
|
||||
public sbyte MinLevel;
|
||||
public sbyte MaxLevel;
|
||||
public sbyte RatedPlayers;
|
||||
public sbyte MinPlayers;
|
||||
public sbyte MaxPlayers;
|
||||
public sbyte GroupsAllowed;
|
||||
public sbyte MaxGroupSize;
|
||||
public ushort HolidayWorldState;
|
||||
public ushort RequiredPlayerConditionID;
|
||||
public byte InstanceType;
|
||||
public byte GroupsAllowed;
|
||||
public byte MaxGroupSize;
|
||||
public byte MinLevel;
|
||||
public byte MaxLevel;
|
||||
public byte RatedPlayers;
|
||||
public byte MinPlayers;
|
||||
public byte MaxPlayers;
|
||||
public byte Flags;
|
||||
public sbyte Flags;
|
||||
public int IconFileDataID;
|
||||
public short RequiredPlayerConditionID;
|
||||
public short[] MapId = new short[16];
|
||||
}
|
||||
|
||||
public sealed class BroadcastTextRecord
|
||||
{
|
||||
public uint Id;
|
||||
public LocalizedString Text;
|
||||
public LocalizedString Text1;
|
||||
public uint Id;
|
||||
public byte LanguageID;
|
||||
public int ConditionID;
|
||||
public ushort EmotesID;
|
||||
public byte Flags;
|
||||
public uint ChatBubbleDurationMs;
|
||||
public uint[] SoundEntriesID = new uint[2];
|
||||
public ushort[] EmoteID = new ushort[3];
|
||||
public ushort[] EmoteDelay = new ushort[3];
|
||||
public ushort EmotesID;
|
||||
public byte LanguageID;
|
||||
public byte Flags;
|
||||
public uint ConditionID;
|
||||
public uint[] SoundEntriesID = new uint[2];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,19 @@ using Framework.GameMath;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
public sealed class Cfg_RegionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Tag;
|
||||
public ushort RegionID;
|
||||
public uint Raidorigin; // Date of first raid reset, all other resets are calculated as this date plus interval
|
||||
public byte RegionGroupMask;
|
||||
public uint ChallengeOrigin;
|
||||
}
|
||||
|
||||
public sealed class CharacterFacialHairStylesRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint Id;
|
||||
public int[] Geoset = new int[5];
|
||||
public byte RaceID;
|
||||
public byte SexID;
|
||||
@@ -31,34 +41,34 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class CharBaseSectionRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint Id;
|
||||
public byte LayoutResType;
|
||||
public CharBaseSectionVariation VariationEnum;
|
||||
public byte ResolutionVariationEnum;
|
||||
public byte LayoutResType;
|
||||
}
|
||||
|
||||
public sealed class CharSectionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint[] MaterialResourcesID = new uint[3];
|
||||
public short Flags;
|
||||
public byte RaceID;
|
||||
public byte SexID;
|
||||
public byte BaseSection;
|
||||
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 int[] ItemID = new int[24];
|
||||
public uint PetDisplayID;
|
||||
public byte ClassID;
|
||||
public byte SexID;
|
||||
public byte OutfitID;
|
||||
public byte PetFamilyID;
|
||||
public uint RaceID;
|
||||
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 byte RaceID;
|
||||
}
|
||||
|
||||
public sealed class CharTitlesRecord
|
||||
@@ -81,75 +91,83 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class ChrClassesRecord
|
||||
{
|
||||
public string PetNameToken;
|
||||
public LocalizedString Name;
|
||||
public string NameFemale;
|
||||
public string Filename;
|
||||
public string NameMale;
|
||||
public uint FileName;
|
||||
public string NameFemale;
|
||||
public string PetNameToken;
|
||||
public uint Id;
|
||||
public uint CreateScreenFileDataID;
|
||||
public uint SelectScreenFileDataID;
|
||||
public uint LowResScreenFileDataID;
|
||||
public uint IconFileDataID;
|
||||
public uint LowResScreenFileDataID;
|
||||
public int StartingLevel;
|
||||
public ushort Flags;
|
||||
public ushort CinematicSequenceID;
|
||||
public ushort DefaultSpec;
|
||||
public PowerType DisplayPower;
|
||||
public byte SpellClassSet;
|
||||
public byte AttackPowerPerStrength;
|
||||
public byte AttackPowerPerAgility;
|
||||
public byte RangedAttackPowerPerAgility;
|
||||
public byte PrimaryStatPriority;
|
||||
public uint Id;
|
||||
public PowerType DisplayPower;
|
||||
public byte RangedAttackPowerPerAgility;
|
||||
public byte AttackPowerPerAgility;
|
||||
public byte AttackPowerPerStrength;
|
||||
public byte SpellClassSet;
|
||||
}
|
||||
|
||||
public sealed class ChrClassesXPowerTypesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte PowerType;
|
||||
public uint ClassID;
|
||||
public sbyte PowerType;
|
||||
public byte ClassID;
|
||||
}
|
||||
|
||||
public sealed class ChrRacesRecord
|
||||
{
|
||||
public uint ClientPrefix;
|
||||
public uint ClientFileString;
|
||||
public string ClientPrefix;
|
||||
public string ClientFileString;
|
||||
public LocalizedString Name;
|
||||
public string NameFemale;
|
||||
public string NameLowercase;
|
||||
public string NameFemaleLowercase;
|
||||
public uint Id;
|
||||
public int Flags;
|
||||
public uint MaleDisplayId;
|
||||
public uint FemaleDisplayId;
|
||||
public uint HighResMaleDisplayId;
|
||||
public uint HighResFemaleDisplayId;
|
||||
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 ushort FactionID;
|
||||
public ushort CinematicSequenceID;
|
||||
public short ResSicknessSpellID;
|
||||
public short SplashSoundID;
|
||||
public ushort CinematicSequenceID;
|
||||
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 DisplayRaceID;
|
||||
public sbyte CharComponentTexLayoutHiResID;
|
||||
public uint Id;
|
||||
public uint HighResMaleDisplayId;
|
||||
public uint HighResFemaleDisplayId;
|
||||
public int HeritageArmorAchievementID;
|
||||
public int MaleSkeletonFileDataID;
|
||||
public int FemaleSkeletonFileDataID;
|
||||
public uint[] AlteredFormStartVisualKitID = new uint[3];
|
||||
public uint[] AlteredFormFinishVisualKitID = new uint[3];
|
||||
public sbyte MaleModelFallbackRaceID;
|
||||
public sbyte MaleModelFallbackSex;
|
||||
public sbyte FemaleModelFallbackRaceID;
|
||||
public sbyte FemaleModelFallbackSex;
|
||||
public sbyte MaleTextureFallbackRaceID;
|
||||
public sbyte MaleTextureFallbackSex;
|
||||
public sbyte FemaleTextureFallbackRaceID;
|
||||
public sbyte FemaleTextureFallbackSex;
|
||||
}
|
||||
|
||||
public sealed class ChrSpecializationRecord
|
||||
@@ -157,16 +175,16 @@ namespace Game.DataStorage
|
||||
public string Name;
|
||||
public string FemaleName;
|
||||
public string Description;
|
||||
public uint[] MasterySpellID = new uint[PlayerConst.MaxMasterySpells];
|
||||
public uint Id;
|
||||
public byte ClassID;
|
||||
public byte OrderIndex;
|
||||
public byte PetTalentType;
|
||||
public byte Role;
|
||||
public byte PrimaryStatPriority;
|
||||
public uint Id;
|
||||
public int SpellIconFileID;
|
||||
public sbyte PetTalentType;
|
||||
public sbyte Role;
|
||||
public ChrSpecializationFlag Flags;
|
||||
public int SpellIconFileID;
|
||||
public sbyte PrimaryStatPriority;
|
||||
public int AnimReplacements;
|
||||
public uint[] MasterySpellID = new uint[PlayerConst.MaxMasterySpells];
|
||||
|
||||
public bool IsPetSpecialization()
|
||||
{
|
||||
@@ -176,11 +194,11 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class CinematicCameraRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint SoundID;
|
||||
public Vector3 Origin;
|
||||
public float OriginFacing;
|
||||
public uint FileDataID;
|
||||
public uint Id;
|
||||
public Vector3 Origin; // Position in map used for basis for M2 co-ordinates
|
||||
public uint SoundID; // Sound ID (voiceover for cinematic)
|
||||
public float OriginFacing; // Orientation in map used for basis for M2 co
|
||||
public uint FileDataID; // Model
|
||||
}
|
||||
|
||||
public sealed class CinematicSequencesRecord
|
||||
@@ -190,6 +208,16 @@ namespace Game.DataStorage
|
||||
public ushort[] Camera = new ushort[8];
|
||||
}
|
||||
|
||||
public sealed class ContentTuningRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int MinLevel;
|
||||
public int MaxLevel;
|
||||
public int Flags;
|
||||
public int ExpectedStatModID;
|
||||
public int DifficultyESMID;
|
||||
}
|
||||
|
||||
public sealed class ConversationLineRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -206,45 +234,47 @@ namespace Game.DataStorage
|
||||
public sealed class CreatureDisplayInfoRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float CreatureModelScale;
|
||||
public ushort ModelID;
|
||||
public ushort NPCSoundID;
|
||||
public byte SizeClass;
|
||||
public byte Flags;
|
||||
public sbyte Gender;
|
||||
public uint ExtendedDisplayInfoID;
|
||||
public uint PortraitTextureFileDataID;
|
||||
public byte CreatureModelAlpha;
|
||||
public ushort SoundID;
|
||||
public float PlayerOverrideScale;
|
||||
public uint PortraitCreatureDisplayInfoID;
|
||||
public sbyte SizeClass;
|
||||
public float CreatureModelScale;
|
||||
public byte CreatureModelAlpha;
|
||||
public byte BloodID;
|
||||
public int ExtendedDisplayInfoID;
|
||||
public ushort NPCSoundID;
|
||||
public ushort ParticleColorID;
|
||||
public uint CreatureGeosetData;
|
||||
public int PortraitCreatureDisplayInfoID;
|
||||
public int PortraitTextureFileDataID;
|
||||
public ushort ObjectEffectPackageID;
|
||||
public ushort AnimReplacementSetID;
|
||||
public byte Flags;
|
||||
public int StateSpellVisualKitID;
|
||||
public float PlayerOverrideScale;
|
||||
public float PetInstanceScale; // scale of not own player pets inside dungeons/raids/scenarios
|
||||
public sbyte UnarmedWeaponType;
|
||||
public uint StateSpellVisualKitID;
|
||||
public float PetInstanceScale; // scale of not own player pets inside dungeons/raids/scenarios
|
||||
public uint MountPoofSpellVisualKitID;
|
||||
public uint[] TextureVariationFileDataID = new uint[3];
|
||||
public int MountPoofSpellVisualKitID;
|
||||
public int DissolveEffectID;
|
||||
public sbyte Gender;
|
||||
public int DissolveOutEffectID;
|
||||
public sbyte CreatureModelMinLod;
|
||||
public int[] TextureVariationFileDataID = new int[3];
|
||||
}
|
||||
|
||||
public sealed class CreatureDisplayInfoExtraRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint BakeMaterialResourcesID;
|
||||
public uint HDBakeMaterialResourcesID;
|
||||
public byte DisplayRaceID;
|
||||
public byte DisplaySexID;
|
||||
public byte DisplayClassID;
|
||||
public byte SkinID;
|
||||
public byte FaceID;
|
||||
public byte HairStyleID;
|
||||
public byte HairColorID;
|
||||
public byte FacialHairID;
|
||||
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 byte Flags;
|
||||
}
|
||||
|
||||
public sealed class CreatureFamilyRecord
|
||||
@@ -252,46 +282,46 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public LocalizedString Name;
|
||||
public float MinScale;
|
||||
public sbyte MinScaleLevel;
|
||||
public float MaxScale;
|
||||
public uint IconFileID;
|
||||
public ushort[] SkillLine = new ushort[2];
|
||||
public sbyte MaxScaleLevel;
|
||||
public ushort PetFoodMask;
|
||||
public byte MinScaleLevel;
|
||||
public byte MaxScaleLevel;
|
||||
public byte PetTalentType;
|
||||
public sbyte PetTalentType;
|
||||
public int IconFileID;
|
||||
public short[] SkillLine = new short[2];
|
||||
}
|
||||
|
||||
public sealed class CreatureModelDataRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float ModelScale;
|
||||
public float[] GeoBox = new float[6];
|
||||
public uint Flags;
|
||||
public uint FileDataID;
|
||||
public uint BloodID;
|
||||
public uint FootprintTextureID;
|
||||
public float FootprintTextureLength;
|
||||
public float FootprintTextureWidth;
|
||||
public float FootprintParticleScale;
|
||||
public uint FoleyMaterialID;
|
||||
public uint FootstepCameraEffectID;
|
||||
public uint DeathThudCameraEffectID;
|
||||
public uint SoundID;
|
||||
public uint SizeClass;
|
||||
public float CollisionWidth;
|
||||
public float CollisionHeight;
|
||||
public float MountHeight;
|
||||
public float[] GeoBox = new float[6];
|
||||
public float CollisionHeight;
|
||||
public float WorldEffectScale;
|
||||
public uint CreatureGeosetDataID;
|
||||
public float HoverHeight;
|
||||
public float AttachedEffectScale;
|
||||
public float ModelScale;
|
||||
public float MissileCollisionRadius;
|
||||
public float MissileCollisionPush;
|
||||
public float MissileCollisionRaise;
|
||||
public float MountHeight;
|
||||
public float OverrideLootEffectScale;
|
||||
public float OverrideNameScale;
|
||||
public float OverrideSelectionRadius;
|
||||
public float TamedPetBaseScale;
|
||||
public float HoverHeight;
|
||||
public uint Flags;
|
||||
public uint FileDataID;
|
||||
public byte SizeClass;
|
||||
public uint BloodID;
|
||||
public byte FootprintTextureID;
|
||||
public byte FoleyMaterialID;
|
||||
public byte FootstepCameraEffectID;
|
||||
public byte DeathThudCameraEffectID;
|
||||
public uint SoundID;
|
||||
public uint CreatureGeosetDataID;
|
||||
}
|
||||
|
||||
public sealed class CreatureTypeRecord
|
||||
@@ -304,16 +334,16 @@ namespace Game.DataStorage
|
||||
public sealed class CriteriaRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint Asset;
|
||||
public uint StartAsset;
|
||||
public uint FailAsset;
|
||||
public uint ModifierTreeId;
|
||||
public ushort StartTimer;
|
||||
public ushort EligibilityWorldStateID;
|
||||
public CriteriaTypes Type;
|
||||
public uint Asset;
|
||||
public uint ModifierTreeId;
|
||||
public CriteriaTimedTypes StartEvent;
|
||||
public uint StartAsset;
|
||||
public ushort StartTimer;
|
||||
public byte FailEvent;
|
||||
public uint FailAsset;
|
||||
public byte Flags;
|
||||
public ushort EligibilityWorldStateID;
|
||||
public byte EligibilityWorldStateValue;
|
||||
}
|
||||
|
||||
@@ -321,12 +351,12 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public string Description;
|
||||
public uint Parent;
|
||||
public uint Amount;
|
||||
public CriteriaTreeFlags Flags;
|
||||
public byte Operator;
|
||||
public ushort CriteriaID;
|
||||
public ushort Parent;
|
||||
public sbyte Operator;
|
||||
public uint CriteriaID;
|
||||
public int OrderIndex;
|
||||
public CriteriaTreeFlags Flags;
|
||||
}
|
||||
|
||||
public sealed class CurrencyTypesRecord
|
||||
@@ -334,19 +364,20 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string Description;
|
||||
public byte CategoryID;
|
||||
public int InventoryIconFileID;
|
||||
public uint SpellWeight;
|
||||
public byte SpellCategory;
|
||||
public uint MaxQty;
|
||||
public uint MaxEarnablePerWeek;
|
||||
public CurrencyFlags Flags;
|
||||
public byte CategoryID;
|
||||
public byte SpellCategory;
|
||||
public byte Quality;
|
||||
public uint InventoryIconFileID;
|
||||
public uint SpellWeight;
|
||||
public uint Flags;
|
||||
public sbyte Quality;
|
||||
public int FactionID;
|
||||
}
|
||||
|
||||
public sealed class CurveRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint Id;
|
||||
public byte Type;
|
||||
public byte Flags;
|
||||
}
|
||||
|
||||
@@ -22,59 +22,59 @@ namespace Game.DataStorage
|
||||
public sealed class DestructibleModelDataRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort State0Wmo;
|
||||
public ushort State1Wmo;
|
||||
public ushort State2Wmo;
|
||||
public ushort State3Wmo;
|
||||
public ushort HealEffectSpeed;
|
||||
public byte State0ImpactEffectDoodadSet;
|
||||
public sbyte State0ImpactEffectDoodadSet;
|
||||
public byte State0AmbientDoodadSet;
|
||||
public byte State0NameSet;
|
||||
public byte State1DestructionDoodadSet;
|
||||
public byte State1ImpactEffectDoodadSet;
|
||||
public ushort State1Wmo;
|
||||
public sbyte State1DestructionDoodadSet;
|
||||
public sbyte State1ImpactEffectDoodadSet;
|
||||
public byte State1AmbientDoodadSet;
|
||||
public byte State1NameSet;
|
||||
public byte State2DestructionDoodadSet;
|
||||
public byte State2ImpactEffectDoodadSet;
|
||||
public ushort State2Wmo;
|
||||
public sbyte State2DestructionDoodadSet;
|
||||
public sbyte State2ImpactEffectDoodadSet;
|
||||
public byte State2AmbientDoodadSet;
|
||||
public byte State2NameSet;
|
||||
public ushort State3Wmo;
|
||||
public byte State3InitDoodadSet;
|
||||
public byte State3AmbientDoodadSet;
|
||||
public byte State3NameSet;
|
||||
public byte EjectDirection;
|
||||
public byte DoNotHighlight;
|
||||
public ushort State0Wmo;
|
||||
public byte HealEffect;
|
||||
public ushort HealEffectSpeed;
|
||||
public byte State0NameSet;
|
||||
public byte State1NameSet;
|
||||
public byte State2NameSet;
|
||||
public byte State3NameSet;
|
||||
}
|
||||
|
||||
public sealed class DifficultyRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public MapTypes InstanceType;
|
||||
public byte OrderIndex;
|
||||
public sbyte OldEnumValue;
|
||||
public byte FallbackDifficultyID;
|
||||
public byte MinPlayers;
|
||||
public byte MaxPlayers;
|
||||
public DifficultyFlags Flags;
|
||||
public byte ItemContext;
|
||||
public byte ToggleDifficultyID;
|
||||
public ushort GroupSizeHealthCurveID;
|
||||
public ushort GroupSizeDmgCurveID;
|
||||
public ushort GroupSizeSpellPointsCurveID;
|
||||
public byte FallbackDifficultyID;
|
||||
public MapTypes InstanceType;
|
||||
public byte MinPlayers;
|
||||
public byte MaxPlayers;
|
||||
public sbyte OldEnumValue;
|
||||
public DifficultyFlags Flags;
|
||||
public byte ToggleDifficultyID;
|
||||
public byte ItemContext;
|
||||
public byte OrderIndex;
|
||||
}
|
||||
|
||||
public sealed class DungeonEncounterRecord
|
||||
{
|
||||
public LocalizedString Name;
|
||||
public uint CreatureDisplayID;
|
||||
public ushort MapID;
|
||||
public byte DifficultyID;
|
||||
public byte Bit;
|
||||
public byte Flags;
|
||||
public uint Id;
|
||||
public uint OrderIndex;
|
||||
public uint SpellIconFileID;
|
||||
public short MapID;
|
||||
public sbyte DifficultyID;
|
||||
public int OrderIndex;
|
||||
public sbyte Bit;
|
||||
public int CreatureDisplayID;
|
||||
public byte Flags;
|
||||
public int SpellIconFileID;
|
||||
}
|
||||
|
||||
public sealed class DurabilityCostsRecord
|
||||
|
||||
@@ -21,30 +21,60 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public long RaceMask;
|
||||
public uint EmoteSlashCommand;
|
||||
public string EmoteSlashCommand;
|
||||
public int AnimId;
|
||||
public uint EmoteFlags;
|
||||
public uint SpellVisualKitID;
|
||||
public ushort AnimID;
|
||||
public byte EmoteSpecProc;
|
||||
public uint EmoteSpecProcParam;
|
||||
public uint EventSoundID;
|
||||
public uint SpellVisualKitId;
|
||||
public int ClassMask;
|
||||
public byte EmoteSpecProcParam;
|
||||
public ushort EmoteSoundID;
|
||||
}
|
||||
|
||||
public sealed class EmotesTextRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public ushort EmoteID;
|
||||
public ushort EmoteId;
|
||||
}
|
||||
|
||||
public sealed class EmotesTextSoundRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte RaceId;
|
||||
public byte SexId;
|
||||
public byte ClassId;
|
||||
public byte SexId;
|
||||
public uint SoundId;
|
||||
public uint EmotesTextId;
|
||||
public ushort EmotesTextId;
|
||||
}
|
||||
|
||||
public sealed class ExpectedStatRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int ExpansionID;
|
||||
public float CreatureHealth;
|
||||
public float PlayerHealth;
|
||||
public float CreatureAutoAttackDps;
|
||||
public float CreatureArmor;
|
||||
public float PlayerMana;
|
||||
public float PlayerPrimaryStat;
|
||||
public float PlayerSecondaryStat;
|
||||
public float ArmorConstant;
|
||||
public float CreatureSpellDamage;
|
||||
public uint Lvl;
|
||||
}
|
||||
|
||||
public sealed class ExpectedStatModRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float CreatureHealthMod;
|
||||
public float PlayerHealthMod;
|
||||
public float CreatureAutoAttackDPSMod;
|
||||
public float CreatureArmorMod;
|
||||
public float PlayerManaMod;
|
||||
public float PlayerPrimaryStatMod;
|
||||
public float PlayerSecondaryStatMod;
|
||||
public float ArmorConstantMod;
|
||||
public float CreatureSpellDamageMod;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,23 +22,24 @@ namespace Game.DataStorage
|
||||
{
|
||||
public sealed class FactionRecord
|
||||
{
|
||||
public long[] ReputationRaceMask = new long[4];
|
||||
public ulong[] ReputationRaceMask = new ulong[4];
|
||||
public LocalizedString Name;
|
||||
public string Description;
|
||||
public uint Id;
|
||||
public int[] ReputationBase = new int[4];
|
||||
public float[] ParentFactionMod = new float[2]; // Faction outputs rep * ParentFactionModOut as spillover reputation
|
||||
public uint[] ReputationMax = new uint[4];
|
||||
public short ReputationIndex;
|
||||
public ushort[] ReputationClassMask = new ushort[4];
|
||||
public ushort[] ReputationFlags = new ushort[4];
|
||||
public ushort ParentFactionID;
|
||||
public ushort ParagonFactionID;
|
||||
public byte[] ParentFactionCap = new byte[2]; // The highest rank the faction will profit from incoming spillover
|
||||
public byte Expansion;
|
||||
public byte Flags;
|
||||
public byte FriendshipRepID;
|
||||
public byte Flags;
|
||||
public ushort ParagonFactionID;
|
||||
public short[] ReputationClassMask = new short[4];
|
||||
public ushort[] ReputationFlags = new ushort[4];
|
||||
public int[] ReputationBase = new int[4];
|
||||
public int[] ReputationMax = new int[4];
|
||||
public float[] ParentFactionMod = new float[2]; // Faction outputs rep * ParentFactionModOut as spillover reputation
|
||||
public byte[] ParentFactionCap = new byte[2]; // The highest rank the faction will profit from incoming spillover
|
||||
|
||||
// helpers
|
||||
public bool CanHaveReputation()
|
||||
{
|
||||
return ReputationIndex >= 0;
|
||||
@@ -50,16 +51,18 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public ushort Faction;
|
||||
public ushort Flags;
|
||||
public ushort[] Enemies = new ushort[4];
|
||||
public ushort[] Friend = new ushort[4];
|
||||
public byte FactionGroup;
|
||||
public byte FriendGroup;
|
||||
public byte EnemyGroup;
|
||||
public ushort[] Enemies = new ushort[4];
|
||||
public ushort[] Friend = new ushort[4];
|
||||
|
||||
// helpers
|
||||
public bool IsFriendlyTo(FactionTemplateRecord entry)
|
||||
{
|
||||
if (Id == entry.Id)
|
||||
if (this == entry)
|
||||
return true;
|
||||
|
||||
if (entry.Faction != 0)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
@@ -69,12 +72,13 @@ namespace Game.DataStorage
|
||||
if (Friend[i] == entry.Faction)
|
||||
return true;
|
||||
}
|
||||
return Convert.ToBoolean(FriendGroup & entry.FactionGroup) || Convert.ToBoolean(FactionGroup & entry.FriendGroup);
|
||||
return (FriendGroup & entry.FactionGroup) != 0 || (FactionGroup & entry.FriendGroup) != 0;
|
||||
}
|
||||
public bool IsHostileTo(FactionTemplateRecord entry)
|
||||
{
|
||||
if (Id == entry.Id)
|
||||
if (this == entry)
|
||||
return false;
|
||||
|
||||
if (entry.Faction != 0)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
@@ -86,16 +90,15 @@ namespace Game.DataStorage
|
||||
}
|
||||
return (EnemyGroup & entry.FactionGroup) != 0;
|
||||
}
|
||||
public bool IsHostileToPlayers() { return (EnemyGroup & (uint)FactionMasks.Player) != 0; }
|
||||
public bool IsHostileToPlayers() { return (EnemyGroup & (byte)FactionMasks.Player) != 0; }
|
||||
public bool IsNeutralToAll()
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (Enemies[i] != 0)
|
||||
return false;
|
||||
|
||||
return EnemyGroup == 0 && FriendGroup == 0;
|
||||
}
|
||||
public bool IsContestedGuardFaction() { return Flags.HasAnyFlag((ushort)FactionTemplateFlags.ContestedGuard); }
|
||||
public bool ShouldSparAttack() { return Flags.HasAnyFlag((ushort)FactionTemplateFlags.EnemySpar); }
|
||||
public bool IsContestedGuardFaction() { return (Flags & (ushort)FactionTemplateFlags.ContestedGuard) != 0; }
|
||||
public bool ShouldSparAttack() { return (Flags & (ushort)FactionTemplateFlags.EnemySpar) != 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,12 +23,12 @@ namespace Game.DataStorage
|
||||
public sealed class GameObjectDisplayInfoRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint FileDataID;
|
||||
public Vector3 GeoBoxMin;
|
||||
public Vector3 GeoBoxMax;
|
||||
public int FileDataID;
|
||||
public short ObjectEffectPackageID;
|
||||
public float OverrideLootEffectScale;
|
||||
public float OverrideNameScale;
|
||||
public ushort ObjectEffectPackageID;
|
||||
}
|
||||
|
||||
public sealed class GameObjectsRecord
|
||||
@@ -36,65 +36,65 @@ namespace Game.DataStorage
|
||||
public LocalizedString Name;
|
||||
public Vector3 Pos;
|
||||
public float[] Rot = new float[4];
|
||||
public float Scale;
|
||||
public int[] PropValue = new int[8];
|
||||
public uint Id;
|
||||
public ushort OwnerID;
|
||||
public ushort DisplayID;
|
||||
public float Scale;
|
||||
public GameObjectTypes TypeID;
|
||||
public byte PhaseUseFlags;
|
||||
public ushort PhaseID;
|
||||
public ushort PhaseGroupID;
|
||||
public byte PhaseUseFlags;
|
||||
public GameObjectTypes TypeID;
|
||||
public uint Id;
|
||||
public int[] PropValue = new int[8];
|
||||
}
|
||||
|
||||
public sealed class GarrAbilityRecord
|
||||
{
|
||||
public string Name;
|
||||
public string Description;
|
||||
public uint IconFileDataID;
|
||||
public GarrisonAbilityFlags Flags;
|
||||
public ushort FactionChangeGarrAbilityID;
|
||||
public uint Id;
|
||||
public byte GarrAbilityCategoryID;
|
||||
public byte GarrFollowerTypeID;
|
||||
public uint Id;
|
||||
public int IconFileDataID;
|
||||
public ushort FactionChangeGarrAbilityID;
|
||||
public GarrisonAbilityFlags Flags;
|
||||
}
|
||||
|
||||
public sealed class GarrBuildingRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string AllianceName;
|
||||
public string HordeName;
|
||||
public string AllianceName;
|
||||
public string Description;
|
||||
public string Tooltip;
|
||||
public byte GarrTypeID;
|
||||
public byte BuildingType;
|
||||
public uint HordeGameObjectID;
|
||||
public uint AllianceGameObjectID;
|
||||
public uint IconFileDataID;
|
||||
public byte GarrSiteID;
|
||||
public byte UpgradeLevel;
|
||||
public int BuildSeconds;
|
||||
public ushort CurrencyTypeID;
|
||||
public int CurrencyQty;
|
||||
public ushort HordeUiTextureKitID;
|
||||
public ushort AllianceUiTextureKitID;
|
||||
public int IconFileDataID;
|
||||
public ushort AllianceSceneScriptPackageID;
|
||||
public ushort HordeSceneScriptPackageID;
|
||||
public int MaxAssignments;
|
||||
public byte ShipmentCapacity;
|
||||
public ushort GarrAbilityID;
|
||||
public ushort BonusGarrAbilityID;
|
||||
public short GoldCost;
|
||||
public byte GarrSiteID;
|
||||
public byte BuildingType;
|
||||
public byte UpgradeLevel;
|
||||
public ushort GoldCost;
|
||||
public GarrisonBuildingFlags Flags;
|
||||
public byte ShipmentCapacity;
|
||||
public byte GarrTypeID;
|
||||
public ushort BuildSeconds;
|
||||
public int CurrencyQty;
|
||||
public byte MaxAssignments;
|
||||
}
|
||||
|
||||
public sealed class GarrBuildingPlotInstRecord
|
||||
{
|
||||
public Vector2 MapOffset;
|
||||
public ushort UiTextureAtlasMemberID;
|
||||
public ushort GarrSiteLevelPlotInstID;
|
||||
public byte GarrBuildingID;
|
||||
public uint Id;
|
||||
public byte GarrBuildingID;
|
||||
public ushort GarrSiteLevelPlotInstID;
|
||||
public ushort UiTextureAtlasMemberID;
|
||||
}
|
||||
|
||||
public sealed class GarrClassSpecRecord
|
||||
@@ -102,11 +102,11 @@ namespace Game.DataStorage
|
||||
public string ClassSpec;
|
||||
public string ClassSpecMale;
|
||||
public string ClassSpecFemale;
|
||||
public ushort UiTextureAtlasMemberID; // UiTextureAtlasMember.db2 ref
|
||||
public uint Id;
|
||||
public ushort UiTextureAtlasMemberID;
|
||||
public ushort GarrFollItemSetID;
|
||||
public byte FollowerClassLimit;
|
||||
public byte Flags;
|
||||
public uint Id;
|
||||
}
|
||||
|
||||
public sealed class GarrFollowerRecord
|
||||
@@ -114,54 +114,55 @@ namespace Game.DataStorage
|
||||
public string HordeSourceText;
|
||||
public string AllianceSourceText;
|
||||
public string TitleName;
|
||||
public uint HordeCreatureID;
|
||||
public uint AllianceCreatureID;
|
||||
public uint HordeIconFileDataID;
|
||||
public uint AllianceIconFileDataID;
|
||||
public uint HordeSlottingBroadcastTextID;
|
||||
public uint AllySlottingBroadcastTextID;
|
||||
public ushort HordeGarrFollItemSetID;
|
||||
public ushort AllianceGarrFollItemSetID;
|
||||
public ushort ItemLevelWeapon;
|
||||
public ushort ItemLevelArmor;
|
||||
public ushort HordeUITextureKitID;
|
||||
public ushort AllianceUITextureKitID;
|
||||
public uint Id;
|
||||
public byte GarrTypeID;
|
||||
public byte GarrFollowerTypeID;
|
||||
public int HordeCreatureID;
|
||||
public int AllianceCreatureID;
|
||||
public byte HordeGarrFollRaceID;
|
||||
public byte AllianceGarrFollRaceID;
|
||||
public byte Quality;
|
||||
public byte HordeGarrClassSpecID;
|
||||
public byte AllianceGarrClassSpecID;
|
||||
public byte Quality;
|
||||
public byte FollowerLevel;
|
||||
public byte Gender;
|
||||
public byte Flags;
|
||||
public ushort ItemLevelWeapon;
|
||||
public ushort ItemLevelArmor;
|
||||
public sbyte HordeSourceTypeEnum;
|
||||
public sbyte AllianceSourceTypeEnum;
|
||||
public byte GarrTypeID;
|
||||
public int HordeIconFileDataID;
|
||||
public int AllianceIconFileDataID;
|
||||
public ushort HordeGarrFollItemSetID;
|
||||
public ushort AllianceGarrFollItemSetID;
|
||||
public ushort HordeUITextureKitID;
|
||||
public ushort AllianceUITextureKitID;
|
||||
public byte Vitality;
|
||||
public byte ChrClassID;
|
||||
public byte HordeFlavorGarrStringID;
|
||||
public byte AllianceFlavorGarrStringID;
|
||||
public uint Id;
|
||||
public uint HordeSlottingBroadcastTextID;
|
||||
public uint AllySlottingBroadcastTextID;
|
||||
public byte ChrClassID;
|
||||
public byte Flags;
|
||||
public byte Gender;
|
||||
}
|
||||
|
||||
public sealed class GarrFollowerXAbilityRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort GarrAbilityID;
|
||||
public byte OrderIndex;
|
||||
public byte FactionIndex;
|
||||
public uint GarrFollowerID;
|
||||
public ushort GarrAbilityID;
|
||||
public ushort GarrFollowerID;
|
||||
}
|
||||
|
||||
public sealed class GarrPlotRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public uint AllianceConstructObjID;
|
||||
public uint HordeConstructObjID;
|
||||
public byte UiCategoryID;
|
||||
public byte PlotType;
|
||||
public uint HordeConstructObjID;
|
||||
public uint AllianceConstructObjID;
|
||||
public byte Flags;
|
||||
public byte UiCategoryID;
|
||||
public uint[] UpgradeRequirement = new uint[2];
|
||||
}
|
||||
|
||||
@@ -183,14 +184,14 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public Vector2 TownHallUiPos;
|
||||
public uint GarrSiteID;
|
||||
public byte GarrLevel;
|
||||
public ushort MapID;
|
||||
public ushort UiTextureKitID;
|
||||
public ushort UpgradeMovieID;
|
||||
public ushort UiTextureKitID;
|
||||
public byte MaxBuildingLevel;
|
||||
public ushort UpgradeCost;
|
||||
public ushort UpgradeGoldCost;
|
||||
public byte GarrLevel;
|
||||
public byte GarrSiteID;
|
||||
public byte MaxBuildingLevel;
|
||||
}
|
||||
|
||||
public sealed class GarrSiteLevelPlotInstRecord
|
||||
@@ -205,16 +206,16 @@ namespace Game.DataStorage
|
||||
public sealed class GemPropertiesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public SocketColor Type;
|
||||
public ushort EnchantId;
|
||||
public SocketColor Type;
|
||||
public ushort MinItemLevel;
|
||||
}
|
||||
|
||||
public sealed class GlyphBindableSpellRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public uint GlyphPropertiesID;
|
||||
public int SpellID;
|
||||
public short GlyphPropertiesID;
|
||||
}
|
||||
|
||||
public sealed class GlyphPropertiesRecord
|
||||
@@ -230,31 +231,31 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public ushort ChrSpecializationID;
|
||||
public uint GlyphPropertiesID;
|
||||
public ushort GlyphPropertiesID;
|
||||
}
|
||||
|
||||
public sealed class GuildColorBackgroundRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte Red;
|
||||
public byte Green;
|
||||
public byte Blue;
|
||||
public byte Green;
|
||||
}
|
||||
|
||||
public sealed class GuildColorBorderRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte Red;
|
||||
public byte Green;
|
||||
public byte Blue;
|
||||
public byte Green;
|
||||
}
|
||||
|
||||
public sealed class GuildColorEmblemRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte Red;
|
||||
public byte Green;
|
||||
public byte Blue;
|
||||
public byte Green;
|
||||
}
|
||||
|
||||
public sealed class GuildPerkSpellsRecord
|
||||
|
||||
@@ -98,11 +98,6 @@ namespace Game.DataStorage
|
||||
public float JewelryMultiplier;
|
||||
}
|
||||
|
||||
public sealed class GtHonorLevelRecord
|
||||
{
|
||||
public float[] Prestige = new float[33];
|
||||
}
|
||||
|
||||
public sealed class GtHpPerStaRecord
|
||||
{
|
||||
public float Health;
|
||||
@@ -170,6 +165,7 @@ namespace Game.DataStorage
|
||||
public float Gem2;
|
||||
public float Gem3;
|
||||
public float Health;
|
||||
public float DamageReplaceStat;
|
||||
}
|
||||
|
||||
public sealed class GtXpRecord
|
||||
|
||||
@@ -22,30 +22,30 @@ namespace Game.DataStorage
|
||||
public sealed class HeirloomRecord
|
||||
{
|
||||
public string SourceText;
|
||||
public uint ItemID;
|
||||
public uint LegacyItemID;
|
||||
public uint LegacyUpgradedItemID;
|
||||
public uint StaticUpgradedItemID;
|
||||
public uint[] UpgradeItemID = new uint[3];
|
||||
public ushort[] UpgradeItemBonusListID = new ushort[3];
|
||||
public byte Flags;
|
||||
public byte SourceTypeEnum;
|
||||
public uint Id;
|
||||
public uint ItemID;
|
||||
public int LegacyUpgradedItemID;
|
||||
public uint StaticUpgradedItemID;
|
||||
public sbyte SourceTypeEnum;
|
||||
public byte Flags;
|
||||
public int LegacyItemID;
|
||||
public int[] UpgradeItemID = new int[3];
|
||||
public ushort[] UpgradeItemBonusListID = new ushort[3];
|
||||
}
|
||||
|
||||
public sealed class HolidaysRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint[] Date = new uint[SharedConst.MaxHolidayDates]; // dates in unix time starting at January, 1, 2000
|
||||
public ushort[] Duration = new ushort[SharedConst.MaxHolidayDurations];
|
||||
public ushort Region;
|
||||
public byte Looping;
|
||||
public byte[] CalendarFlags = new byte[SharedConst.MaxHolidayFlags];
|
||||
public uint HolidayNameID;
|
||||
public uint HolidayDescriptionID;
|
||||
public byte Priority;
|
||||
public sbyte CalendarFilterType;
|
||||
public byte Flags;
|
||||
public ushort HolidayNameID;
|
||||
public ushort HolidayDescriptionID;
|
||||
public ushort[] Duration = new ushort[SharedConst.MaxHolidayDurations];
|
||||
public uint[] Date = new uint[SharedConst.MaxHolidayDates]; // dates in unix time starting at January, 1, 2000
|
||||
public byte[] CalendarFlags = new byte[SharedConst.MaxHolidayFlags];
|
||||
public int[] TextureFileDataID = new int[3];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,30 +49,29 @@ namespace Game.DataStorage
|
||||
public sealed class ItemRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint IconFileDataID;
|
||||
public ItemClass ClassID;
|
||||
public byte SubclassID;
|
||||
public sbyte SoundOverrideSubclassID;
|
||||
public byte Material;
|
||||
public InventoryType inventoryType;
|
||||
public byte SheatheType;
|
||||
public sbyte SoundOverrideSubclassID;
|
||||
public int IconFileDataID;
|
||||
public byte ItemGroupSoundsID;
|
||||
}
|
||||
|
||||
public sealed class ItemAppearanceRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ItemDisplayInfoID;
|
||||
public uint DefaultIconFileDataID;
|
||||
public uint UIOrder;
|
||||
public byte DisplayType;
|
||||
public uint ItemDisplayInfoID;
|
||||
public int DefaultIconFileDataID;
|
||||
public int UiOrder;
|
||||
}
|
||||
|
||||
public sealed class ItemArmorQualityRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float[] QualityMod = new float[7];
|
||||
public ushort ItemLevel;
|
||||
}
|
||||
|
||||
public sealed class ItemArmorShieldRecord
|
||||
@@ -85,17 +84,17 @@ namespace Game.DataStorage
|
||||
public sealed class ItemArmorTotalRecord
|
||||
{
|
||||
public uint Id;
|
||||
public short ItemLevel;
|
||||
public float Cloth;
|
||||
public float Leather;
|
||||
public float Mail;
|
||||
public float Plate;
|
||||
public ushort ItemLevel;
|
||||
}
|
||||
|
||||
public sealed class ItemBagFamilyRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint Name;
|
||||
public string Name;
|
||||
}
|
||||
|
||||
public sealed class ItemBonusRecord
|
||||
@@ -116,11 +115,11 @@ namespace Game.DataStorage
|
||||
public sealed class ItemBonusTreeNodeRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte ItemContext;
|
||||
public ushort ChildItemBonusTreeID;
|
||||
public ushort ChildItemBonusListID;
|
||||
public ushort ChildItemLevelSelectorID;
|
||||
public byte ItemContext;
|
||||
public uint ParentItemBonusTreeID;
|
||||
public ushort ParentItemBonusTreeID;
|
||||
}
|
||||
|
||||
public sealed class ItemChildEquipmentRecord
|
||||
@@ -135,8 +134,8 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public string ClassName;
|
||||
public sbyte ClassID;
|
||||
public float PriceModifier;
|
||||
public byte ClassID;
|
||||
public byte Flags;
|
||||
}
|
||||
|
||||
@@ -145,7 +144,6 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public uint ItemID;
|
||||
}
|
||||
|
||||
// common struct for:
|
||||
// ItemDamageAmmo.dbc
|
||||
// ItemDamageOneHand.dbc
|
||||
@@ -158,71 +156,71 @@ namespace Game.DataStorage
|
||||
public sealed class ItemDamageRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float[] Quality = new float[7];
|
||||
public ushort ItemLevel;
|
||||
public float[] Quality = new float[7];
|
||||
}
|
||||
|
||||
public sealed class ItemDisenchantLootRecord
|
||||
{
|
||||
public uint Id;
|
||||
public sbyte Subclass;
|
||||
public byte Quality;
|
||||
public ushort MinLevel;
|
||||
public ushort MaxLevel;
|
||||
public ushort SkillRequired;
|
||||
public sbyte Subclass;
|
||||
public byte Quality;
|
||||
public sbyte ExpansionID;
|
||||
public uint ClassID;
|
||||
public byte Class;
|
||||
}
|
||||
|
||||
public sealed class ItemEffectRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int SpellID;
|
||||
public int CoolDownMSec;
|
||||
public int CategoryCoolDownMSec;
|
||||
public short Charges;
|
||||
public ushort SpellCategoryID;
|
||||
public ushort ChrSpecializationID;
|
||||
public byte LegacySlotIndex;
|
||||
public ItemSpelltriggerType TriggerType;
|
||||
public uint ParentItemID;
|
||||
public short Charges;
|
||||
public int CoolDownMSec;
|
||||
public int CategoryCoolDownMSec;
|
||||
public ushort SpellCategoryID;
|
||||
public int SpellID;
|
||||
public ushort ChrSpecializationID;
|
||||
public int ParentItemID;
|
||||
}
|
||||
|
||||
public sealed class ItemExtendedCostRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint[] ItemID = new uint[ItemConst.MaxItemExtCostItems]; // required item id
|
||||
public uint[] CurrencyCount = new uint[ItemConst.MaxItemExtCostCurrencies]; // required curency count
|
||||
public ushort[] ItemCount = new ushort[ItemConst.MaxItemExtCostItems]; // required count of 1st item
|
||||
public ushort RequiredArenaRating; // required personal arena rating
|
||||
public ushort[] CurrencyID = new ushort[ItemConst.MaxItemExtCostCurrencies]; // required curency id
|
||||
public byte ArenaBracket; // arena slot restrictions (min slot value)
|
||||
public ushort RequiredArenaRating;
|
||||
public byte ArenaBracket; // arena slot restrictions (min slot value)
|
||||
public byte Flags;
|
||||
public byte MinFactionID;
|
||||
public byte MinReputation;
|
||||
public byte Flags;
|
||||
public byte RequiredAchievement;
|
||||
public byte RequiredAchievement; // required personal arena rating
|
||||
public uint[] ItemID = new uint[ItemConst.MaxItemExtCostItems]; // required item id
|
||||
public ushort[] ItemCount = new ushort[ItemConst.MaxItemExtCostItems]; // required count of 1st item
|
||||
public ushort[] CurrencyID = new ushort[ItemConst.MaxItemExtCostCurrencies]; // required curency id
|
||||
public uint[] CurrencyCount = new uint[ItemConst.MaxItemExtCostCurrencies]; // required curency count
|
||||
}
|
||||
|
||||
public sealed class ItemLevelSelectorRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint Id;
|
||||
public ushort MinItemLevel;
|
||||
public ushort ItemLevelSelectorQualitySetID;
|
||||
}
|
||||
|
||||
public sealed class ItemLevelSelectorQualityRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint Id;
|
||||
public uint QualityItemBonusListID;
|
||||
public byte Quality;
|
||||
public uint ParentILSQualitySetID;
|
||||
public sbyte Quality;
|
||||
public short ParentILSQualitySetID;
|
||||
}
|
||||
|
||||
public sealed class ItemLevelSelectorQualitySetRecord
|
||||
{
|
||||
public uint ID;
|
||||
public ushort IlvlRare;
|
||||
public ushort IlvlEpic;
|
||||
public uint Id;
|
||||
public short IlvlRare;
|
||||
public short IlvlEpic;
|
||||
}
|
||||
|
||||
public sealed class ItemLimitCategoryRecord
|
||||
@@ -237,26 +235,26 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public sbyte AddQuantity;
|
||||
public ushort PlayerConditionID;
|
||||
public uint PlayerConditionID;
|
||||
public uint ParentItemLimitCategoryID;
|
||||
}
|
||||
|
||||
public sealed class ItemModifiedAppearanceRecord
|
||||
{
|
||||
public uint ItemID;
|
||||
public uint Id;
|
||||
public uint ItemID;
|
||||
public byte ItemAppearanceModifierID;
|
||||
public ushort ItemAppearanceID;
|
||||
public byte OrderIndex;
|
||||
public byte TransmogSourceTypeEnum;
|
||||
public sbyte TransmogSourceTypeEnum;
|
||||
}
|
||||
|
||||
public sealed class ItemPriceBaseRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort ItemLevel;
|
||||
public float Armor;
|
||||
public float Weapon;
|
||||
public ushort ItemLevel;
|
||||
}
|
||||
|
||||
public sealed class ItemRandomPropertiesRecord
|
||||
@@ -276,119 +274,119 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class ItemSearchNameRecord
|
||||
{
|
||||
public ulong AllowableRace;
|
||||
public long AllowableRace;
|
||||
public string Display;
|
||||
public uint Id;
|
||||
public uint[] Flags = new uint[3];
|
||||
public ushort ItemLevel;
|
||||
public byte OverallQualityID;
|
||||
public byte ExpansionID;
|
||||
public byte RequiredLevel;
|
||||
public ushort MinFactionID;
|
||||
public byte MinReputation;
|
||||
public short AllowableClass;
|
||||
public int AllowableClass;
|
||||
public sbyte RequiredLevel;
|
||||
public ushort RequiredSkill;
|
||||
public ushort RequiredSkillRank;
|
||||
public uint RequiredAbility;
|
||||
public ushort ItemLevel;
|
||||
public int[] Flags = new int[4];
|
||||
}
|
||||
|
||||
public sealed class ItemSetRecord
|
||||
{
|
||||
public uint Id;
|
||||
public LocalizedString Name;
|
||||
public uint[] ItemID = new uint[17];
|
||||
public ushort RequiredSkillRank;
|
||||
public byte RequiredSkill;
|
||||
public ItemSetFlags SetFlags;
|
||||
public uint RequiredSkill;
|
||||
public ushort RequiredSkillRank;
|
||||
public uint[] ItemID = new uint[ItemConst.MaxItemSetItems];
|
||||
}
|
||||
|
||||
public sealed class ItemSetSpellRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public ushort ChrSpecID;
|
||||
public uint SpellID;
|
||||
public byte Threshold;
|
||||
public uint ItemSetID;
|
||||
public ushort ItemSetID;
|
||||
}
|
||||
|
||||
public sealed class ItemSparseRecord
|
||||
{
|
||||
public uint Id;
|
||||
public long AllowableRace;
|
||||
public LocalizedString Display;
|
||||
public string Display2;
|
||||
public string Display3;
|
||||
public string Display4;
|
||||
public string Description;
|
||||
public uint[] Flags = new uint[4];
|
||||
public float PriceRandomValue;
|
||||
public float PriceVariance;
|
||||
public uint VendorStackCount;
|
||||
public uint BuyPrice;
|
||||
public uint SellPrice;
|
||||
public uint RequiredAbility;
|
||||
public uint MaxCount;
|
||||
public uint Stackable;
|
||||
public int[] StatPercentEditor = new int[ItemConst.MaxStats];
|
||||
public float[] StatPercentageOfSocket = new float[ItemConst.MaxStats];
|
||||
public float ItemRange;
|
||||
public uint BagFamily;
|
||||
public float QualityModifier;
|
||||
public uint DurationInInventory;
|
||||
public string Display3;
|
||||
public string Display2;
|
||||
public string Display1;
|
||||
public LocalizedString Display;
|
||||
public float DmgVariance;
|
||||
public short AllowableClass;
|
||||
public ushort ItemLevel;
|
||||
public ushort RequiredSkill;
|
||||
public ushort RequiredSkillRank;
|
||||
public ushort MinFactionID;
|
||||
public short[] ItemStatValue = new short[ItemConst.MaxStats];
|
||||
public ushort ScalingStatDistributionID;
|
||||
public ushort ItemDelay;
|
||||
public ushort PageID;
|
||||
public ushort StartQuestID;
|
||||
public ushort LockID;
|
||||
public ushort RandomSelect;
|
||||
public ushort ItemRandomSuffixGroupID;
|
||||
public ushort ItemSet;
|
||||
public ushort ZoneBound;
|
||||
public ushort InstanceBound;
|
||||
public ushort TotemCategoryID;
|
||||
public ushort SocketMatchEnchantmentId;
|
||||
public ushort GemProperties;
|
||||
public ushort LimitCategory;
|
||||
public ushort RequiredHoliday;
|
||||
public ushort RequiredTransmogHoliday;
|
||||
public uint DurationInInventory;
|
||||
public float QualityModifier;
|
||||
public uint BagFamily;
|
||||
public float ItemRange;
|
||||
public float[] StatPercentageOfSocket = new float[ItemConst.MaxStats];
|
||||
public int[] StatPercentEditor = new int[ItemConst.MaxStats];
|
||||
public uint Stackable;
|
||||
public uint MaxCount;
|
||||
public uint RequiredAbility;
|
||||
public uint SellPrice;
|
||||
public uint BuyPrice;
|
||||
public uint VendorStackCount;
|
||||
public float PriceVariance;
|
||||
public float PriceRandomValue;
|
||||
public uint[] Flags = new uint[4];
|
||||
public int FactionRelated;
|
||||
public ushort ItemNameDescriptionID;
|
||||
public byte OverallQualityID;
|
||||
public InventoryType inventoryType;
|
||||
public sbyte RequiredLevel;
|
||||
public byte RequiredPVPRank;
|
||||
public byte RequiredPVPMedal;
|
||||
public byte MinReputation;
|
||||
public byte ContainerSlots;
|
||||
public sbyte[] StatModifierBonusStat = new sbyte[ItemConst.MaxStats];
|
||||
public byte DamageType;
|
||||
public byte Bonding;
|
||||
public byte LanguageID;
|
||||
public byte PageMaterialID;
|
||||
public sbyte Material;
|
||||
public byte SheatheType;
|
||||
public byte[] SocketType = new byte[ItemConst.MaxGemSockets];
|
||||
public byte SpellWeightCategory;
|
||||
public byte SpellWeight;
|
||||
public byte ArtifactID;
|
||||
public ushort RequiredTransmogHoliday;
|
||||
public ushort RequiredHoliday;
|
||||
public ushort LimitCategory;
|
||||
public ushort GemProperties;
|
||||
public ushort SocketMatchEnchantmentId;
|
||||
public ushort TotemCategoryID;
|
||||
public ushort InstanceBound;
|
||||
public ushort ZoneBound;
|
||||
public ushort ItemSet;
|
||||
public ushort ItemRandomSuffixGroupID;
|
||||
public ushort RandomSelect;
|
||||
public ushort LockID;
|
||||
public ushort StartQuestID;
|
||||
public ushort PageID;
|
||||
public ushort ItemDelay;
|
||||
public ushort ScalingStatDistributionID;
|
||||
public ushort MinFactionID;
|
||||
public ushort RequiredSkillRank;
|
||||
public ushort RequiredSkill;
|
||||
public ushort ItemLevel;
|
||||
public short AllowableClass;
|
||||
public byte ExpansionID;
|
||||
public byte ArtifactID;
|
||||
public byte SpellWeight;
|
||||
public byte SpellWeightCategory;
|
||||
public byte[] SocketType = new byte[ItemConst.MaxGemSockets];
|
||||
public byte SheatheType;
|
||||
public byte Material;
|
||||
public byte PageMaterialID;
|
||||
public byte LanguageID;
|
||||
public byte Bonding;
|
||||
public byte DamageType;
|
||||
public sbyte[] StatModifierBonusStat = new sbyte[ItemConst.MaxStats];
|
||||
public byte ContainerSlots;
|
||||
public byte MinReputation;
|
||||
public byte RequiredPVPMedal;
|
||||
public byte RequiredPVPRank;
|
||||
public sbyte RequiredLevel;
|
||||
public InventoryType inventoryType;
|
||||
public byte OverallQualityID;
|
||||
}
|
||||
|
||||
public sealed class ItemSpecRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort SpecializationID;
|
||||
public byte MinLevel;
|
||||
public byte MaxLevel;
|
||||
public byte ItemType;
|
||||
public ItemSpecStat PrimaryStat;
|
||||
public ItemSpecStat SecondaryStat;
|
||||
public ushort SpecializationID;
|
||||
}
|
||||
|
||||
public sealed class ItemSpecOverrideRecord
|
||||
@@ -401,11 +399,11 @@ namespace Game.DataStorage
|
||||
public sealed class ItemUpgradeRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint CurrencyAmount;
|
||||
public ushort PrerequisiteID;
|
||||
public ushort CurrencyType;
|
||||
public byte ItemUpgradePathID;
|
||||
public byte ItemLevelIncrement;
|
||||
public ushort PrerequisiteID;
|
||||
public ushort CurrencyType;
|
||||
public uint CurrencyAmount;
|
||||
}
|
||||
|
||||
public sealed class ItemXBonusTreeRecord
|
||||
|
||||
@@ -25,37 +25,37 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public LocalizedString Name;
|
||||
public string Description;
|
||||
public LfgFlags Flags;
|
||||
public float MinGear;
|
||||
public byte MinLevel;
|
||||
public ushort MaxLevel;
|
||||
public ushort TargetLevelMax;
|
||||
public LfgType TypeID;
|
||||
public byte Subtype;
|
||||
public sbyte Faction;
|
||||
public int IconTextureFileID;
|
||||
public int RewardsBgTextureFileID;
|
||||
public int PopupBgTextureFileID;
|
||||
public byte ExpansionLevel;
|
||||
public short MapID;
|
||||
public Difficulty DifficultyID;
|
||||
public float MinGear;
|
||||
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;
|
||||
public ushort BonusReputationAmount;
|
||||
public ushort MentorItemLevel;
|
||||
public ushort RequiredPlayerConditionId;
|
||||
public byte MinLevel;
|
||||
public byte TargetLevel;
|
||||
public byte TargetLevelMin;
|
||||
public Difficulty DifficultyID;
|
||||
public LfgType TypeID;
|
||||
public byte Faction;
|
||||
public byte ExpansionLevel;
|
||||
public byte OrderIndex;
|
||||
public byte GroupID;
|
||||
public byte CountTank;
|
||||
public byte CountHealer;
|
||||
public byte CountDamage;
|
||||
public byte MinCountTank;
|
||||
public byte MinCountHealer;
|
||||
public byte MinCountDamage;
|
||||
public byte Subtype;
|
||||
public ushort BonusReputationAmount;
|
||||
public ushort MentorItemLevel;
|
||||
public byte MentorCharLevel;
|
||||
public int IconTextureFileID;
|
||||
public int RewardsBgTextureFileID;
|
||||
public int PopupBgTextureFileID;
|
||||
public LfgFlags[] Flags = new LfgFlags[2];
|
||||
|
||||
// Helpers
|
||||
public uint Entry() { return (uint)(Id + ((int)TypeID << 24)); }
|
||||
@@ -67,7 +67,7 @@ namespace Game.DataStorage
|
||||
public Vector3 GameCoords;
|
||||
public float GameFalloffStart;
|
||||
public float GameFalloffEnd;
|
||||
public ushort ContinentID;
|
||||
public short ContinentID;
|
||||
public ushort[] LightParamsID = new ushort[8];
|
||||
}
|
||||
|
||||
@@ -76,29 +76,31 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string[] Texture = new string[6];
|
||||
public ushort Flags;
|
||||
public byte SoundBank; // used to be "type", maybe needs fixing (works well for now)
|
||||
public uint SoundID;
|
||||
public uint SpellID;
|
||||
public float MaxDarkenDepth;
|
||||
public float FogDarkenIntensity;
|
||||
public float AmbDarkenIntensity;
|
||||
public float DirDarkenIntensity;
|
||||
public float ParticleScale;
|
||||
public uint[] Color = new uint[2];
|
||||
public float[] Float = new float[18];
|
||||
public uint[] Int = new uint[4];
|
||||
public ushort Flags;
|
||||
public ushort LightID;
|
||||
public byte SoundBank;
|
||||
public float ParticleScale;
|
||||
public byte ParticleMovement;
|
||||
public byte ParticleTexSlots;
|
||||
public byte MaterialID;
|
||||
public int MinimapStaticCol;
|
||||
public byte[] FrameCountTexture = new byte[6];
|
||||
public ushort SoundID;
|
||||
public int[] Color = new int[2];
|
||||
public float[] Float = new float[18];
|
||||
public uint[] Int = new uint[4];
|
||||
public float[] Coefficient = new float[4];
|
||||
}
|
||||
|
||||
public sealed class LockRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint[] Index = new uint[SharedConst.MaxLockCase];
|
||||
public int[] Index = new int[SharedConst.MaxLockCase];
|
||||
public ushort[] Skill = new ushort[SharedConst.MaxLockCase];
|
||||
public byte[] LockType = new byte[SharedConst.MaxLockCase];
|
||||
public byte[] Action = new byte[SharedConst.MaxLockCase];
|
||||
|
||||
@@ -35,32 +35,32 @@ namespace Game.DataStorage
|
||||
public string MapDescription1; // Alliance
|
||||
public string PvpShortDescription;
|
||||
public string PvpLongDescription;
|
||||
public MapFlags[] Flags = new MapFlags[2];
|
||||
public float MinimapIconScale;
|
||||
public Vector2 Corpse; // entrance coordinates in ghost mode (in most cases = normal entrance)
|
||||
public Vector2 Corpse; // entrance coordinates in ghost mode (in most cases = normal entrance)
|
||||
public byte MapType;
|
||||
public MapTypes InstanceType;
|
||||
public byte ExpansionID;
|
||||
public ushort AreaTableID;
|
||||
public ushort LoadingScreenID;
|
||||
public short CorpseMapID; // map_id of entrance map in ghost mode (continent always and in most cases = normal entrance)
|
||||
public ushort TimeOfDayOverride;
|
||||
public short LoadingScreenID;
|
||||
public short TimeOfDayOverride;
|
||||
public short ParentMapID;
|
||||
public short CosmeticParentMapID;
|
||||
public ushort WindSettingsID;
|
||||
public MapTypes InstanceType;
|
||||
public byte MapType;
|
||||
public byte ExpansionID;
|
||||
public byte MaxPlayers;
|
||||
public byte TimeOffset;
|
||||
public float MinimapIconScale;
|
||||
public short CorpseMapID; // map_id of entrance map in ghost mode (continent always and in most cases = normal entrance)
|
||||
public byte MaxPlayers;
|
||||
public short WindSettingsID;
|
||||
public int ZmpFileDataID;
|
||||
public MapFlags[] Flags = new MapFlags[2];
|
||||
|
||||
//Helpers
|
||||
// Helpers
|
||||
public Expansion Expansion() { return (Expansion)ExpansionID; }
|
||||
|
||||
public bool IsDungeon() { return (InstanceType == MapTypes.Instance || InstanceType == MapTypes.Raid || InstanceType == MapTypes.Scenario) && !IsGarrison(); }
|
||||
public bool IsNonRaidDungeon() { return InstanceType == MapTypes.Instance; }
|
||||
public bool Instanceable()
|
||||
public bool IsDungeon()
|
||||
{
|
||||
return InstanceType == MapTypes.Instance || InstanceType == MapTypes.Raid
|
||||
|| InstanceType == MapTypes.Battleground || InstanceType == MapTypes.Arena || InstanceType == MapTypes.Scenario;
|
||||
return (InstanceType == MapTypes.Instance || InstanceType == MapTypes.Raid || InstanceType == MapTypes.Scenario) && !IsGarrison();
|
||||
}
|
||||
public bool IsNonRaidDungeon() { return InstanceType == MapTypes.Instance; }
|
||||
public bool Instanceable() { return InstanceType == MapTypes.Instance || InstanceType == MapTypes.Raid || InstanceType == MapTypes.Battleground || InstanceType == MapTypes.Arena || InstanceType == MapTypes.Scenario; }
|
||||
public bool IsRaid() { return InstanceType == MapTypes.Raid; }
|
||||
public bool IsBattleground() { return InstanceType == MapTypes.Battleground; }
|
||||
public bool IsBattleArena() { return InstanceType == MapTypes.Arena; }
|
||||
@@ -75,6 +75,7 @@ namespace Game.DataStorage
|
||||
|
||||
if (CorpseMapID < 0)
|
||||
return false;
|
||||
|
||||
mapid = (uint)CorpseMapID;
|
||||
x = Corpse.X;
|
||||
y = Corpse.Y;
|
||||
@@ -86,22 +87,23 @@ namespace Game.DataStorage
|
||||
return Id == 0 || Id == 1 || Id == 530 || Id == 571 || Id == 870 || Id == 1116 || Id == 1220;
|
||||
}
|
||||
|
||||
public bool IsDynamicDifficultyMap() { return Flags[0].HasAnyFlag(MapFlags.CanToggleDifficulty); }
|
||||
public bool IsGarrison() { return Flags[0].HasAnyFlag(MapFlags.Garrison); }
|
||||
public bool IsDynamicDifficultyMap() { return (Flags[0] & MapFlags.CanToggleDifficulty) != 0; }
|
||||
public bool IsGarrison() { return (Flags[0] & MapFlags.Garrison) != 0; }
|
||||
}
|
||||
|
||||
public sealed class MapDifficultyRecord
|
||||
{
|
||||
public uint Id;
|
||||
public LocalizedString Message; // m_message_lang (text showed when transfer to map failed)
|
||||
public byte DifficultyID;
|
||||
public byte ResetInterval; // 1 means daily reset, 2 means weekly
|
||||
public byte MaxPlayers; // m_maxPlayers some heroic versions have 0 when expected same amount as in normal version
|
||||
public byte LockID;
|
||||
public byte Flags;
|
||||
public byte ItemContext;
|
||||
public LocalizedString Message; // m_message_lang (text showed when transfer to map failed)
|
||||
public uint ItemContextPickerID;
|
||||
public uint MapID;
|
||||
public int ContentTuningID;
|
||||
public byte DifficultyID;
|
||||
public byte LockID;
|
||||
public byte ResetInterval;
|
||||
public byte MaxPlayers;
|
||||
public byte ItemContext;
|
||||
public byte Flags;
|
||||
public ushort MapID;
|
||||
|
||||
public uint GetRaidDuration()
|
||||
{
|
||||
@@ -116,42 +118,42 @@ namespace Game.DataStorage
|
||||
public sealed class ModifierTreeRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint Asset;
|
||||
public uint SecondaryAsset;
|
||||
public uint Parent;
|
||||
public sbyte Operator;
|
||||
public sbyte Amount;
|
||||
public byte Type;
|
||||
public byte TertiaryAsset;
|
||||
public byte Operator;
|
||||
public byte Amount;
|
||||
public uint Asset;
|
||||
public int SecondaryAsset;
|
||||
public sbyte TertiaryAsset;
|
||||
}
|
||||
|
||||
public sealed class MountRecord
|
||||
{
|
||||
public string Name;
|
||||
public string Description;
|
||||
public string SourceText;
|
||||
public uint SourceSpellID;
|
||||
public float MountFlyRideHeight;
|
||||
public ushort MountTypeID;
|
||||
public ushort Flags;
|
||||
public byte SourceTypeEnum;
|
||||
public string Description;
|
||||
public uint Id;
|
||||
public ushort MountTypeID;
|
||||
public MountFlags Flags;
|
||||
public sbyte SourceTypeEnum;
|
||||
public uint SourceSpellID;
|
||||
public uint PlayerConditionID;
|
||||
public byte UiModelSceneID;
|
||||
public float MountFlyRideHeight;
|
||||
public int UiModelSceneID;
|
||||
|
||||
public bool IsSelfMount() { return (Flags & (ushort)MountFlags.SelfMount) != 0; }
|
||||
}
|
||||
public bool IsSelfMount() { return (Flags & MountFlags.SelfMount) != 0; }
|
||||
}
|
||||
|
||||
public sealed class MountCapabilityRecord
|
||||
{
|
||||
public uint ReqSpellKnownID;
|
||||
public uint ModSpellAuraID;
|
||||
public uint Id;
|
||||
public MountCapabilityFlags Flags;
|
||||
public ushort ReqRidingSkill;
|
||||
public ushort ReqAreaID;
|
||||
public uint ReqSpellAuraID;
|
||||
public uint ReqSpellKnownID;
|
||||
public uint ModSpellAuraID;
|
||||
public short ReqMapID;
|
||||
public MountCapabilityFlags Flags;
|
||||
public uint Id;
|
||||
public byte ReqSpellAuraID;
|
||||
}
|
||||
|
||||
public sealed class MountTypeXCapabilityRecord
|
||||
@@ -173,9 +175,9 @@ namespace Game.DataStorage
|
||||
public sealed class MovieRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint AudioFileDataID;
|
||||
public uint SubtitleFileDataID;
|
||||
public byte Volume;
|
||||
public byte KeyID;
|
||||
public uint AudioFileDataID;
|
||||
public uint SubtitleFileDataID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,4 +44,12 @@ namespace Game.DataStorage
|
||||
public string Name;
|
||||
public byte LocaleMask;
|
||||
}
|
||||
|
||||
public sealed class NumTalentsAtLevelRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint NumTalents;
|
||||
public uint NumTalentsDeathKnight;
|
||||
public uint NumTalentsDemonHunter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,20 +30,17 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public ushort PhaseId;
|
||||
public uint PhaseGroupID;
|
||||
public ushort PhaseGroupID;
|
||||
}
|
||||
|
||||
public sealed class PlayerConditionRecord
|
||||
{
|
||||
public long RaceMask;
|
||||
public ulong RaceMask;
|
||||
public string FailureDescription;
|
||||
public uint Id;
|
||||
public byte Flags;
|
||||
public ushort MinLevel;
|
||||
public ushort MaxLevel;
|
||||
public int ClassMask;
|
||||
public sbyte Gender;
|
||||
public sbyte NativeGender;
|
||||
public uint SkillLogic;
|
||||
public byte LanguageID;
|
||||
public byte MinLanguage;
|
||||
@@ -51,9 +48,7 @@ namespace Game.DataStorage
|
||||
public ushort MaxFactionID;
|
||||
public byte MaxReputation;
|
||||
public uint ReputationLogic;
|
||||
public byte CurrentPvpFaction;
|
||||
public byte MinPVPRank;
|
||||
public byte MaxPVPRank;
|
||||
public sbyte CurrentPvpFaction;
|
||||
public byte PvpMedal;
|
||||
public uint PrevQuestLogic;
|
||||
public uint CurrQuestLogic;
|
||||
@@ -67,34 +62,39 @@ namespace Game.DataStorage
|
||||
public byte PartyStatus;
|
||||
public byte LifetimeMaxPVPRank;
|
||||
public uint AchievementLogic;
|
||||
public uint LfgLogic;
|
||||
public sbyte Gender;
|
||||
public sbyte NativeGender;
|
||||
public uint AreaLogic;
|
||||
public uint LfgLogic;
|
||||
public uint CurrencyLogic;
|
||||
public ushort QuestKillID;
|
||||
public uint QuestKillLogic;
|
||||
public sbyte MinExpansionLevel;
|
||||
public sbyte MaxExpansionLevel;
|
||||
public sbyte MinExpansionTier;
|
||||
public sbyte MaxExpansionTier;
|
||||
public byte MinGuildLevel;
|
||||
public byte MaxGuildLevel;
|
||||
public byte PhaseUseFlags;
|
||||
public ushort PhaseID;
|
||||
public uint PhaseGroupID;
|
||||
public int MinAvgItemLevel;
|
||||
public int MaxAvgItemLevel;
|
||||
public ushort MinAvgEquippedItemLevel;
|
||||
public ushort MaxAvgEquippedItemLevel;
|
||||
public byte PhaseUseFlags;
|
||||
public ushort PhaseID;
|
||||
public uint PhaseGroupID;
|
||||
public byte Flags;
|
||||
public sbyte ChrSpecializationIndex;
|
||||
public sbyte ChrSpecializationRole;
|
||||
public uint ModifierTreeID;
|
||||
public sbyte PowerType;
|
||||
public byte PowerTypeComp;
|
||||
public byte PowerTypeValue;
|
||||
public uint ModifierTreeID;
|
||||
public int WeaponSubclassMask;
|
||||
public byte MaxGuildLevel;
|
||||
public byte MinGuildLevel;
|
||||
public sbyte MaxExpansionTier;
|
||||
public sbyte MinExpansionTier;
|
||||
public byte MinPVPRank;
|
||||
public byte MaxPVPRank;
|
||||
public ushort[] SkillID = new ushort[4];
|
||||
public short[] MinSkill = new short[4];
|
||||
public short[] MaxSkill = new short[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];
|
||||
@@ -108,12 +108,12 @@ namespace Game.DataStorage
|
||||
public uint[] AuraSpellID = new uint[4];
|
||||
public byte[] AuraStacks = new byte[4];
|
||||
public ushort[] Achievement = new ushort[4];
|
||||
public ushort[] AreaID = new ushort[4];
|
||||
public byte[] LfgStatus = new byte[4];
|
||||
public byte[] LfgCompare = new byte[4];
|
||||
public uint[] LfgValue = new uint[4];
|
||||
public ushort[] AreaID = new ushort[4];
|
||||
public uint[] CurrencyID = new uint[4];
|
||||
public byte[] CurrencyCount = new byte[4];
|
||||
public uint[] CurrencyCount = new uint[4];
|
||||
public uint[] QuestKillMonster = new uint[6];
|
||||
public int[] MovementFlags = new int[2];
|
||||
}
|
||||
@@ -121,7 +121,7 @@ namespace Game.DataStorage
|
||||
public sealed class PowerDisplayRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint GlobalStringBaseTag;
|
||||
public string GlobalStringBaseTag;
|
||||
public byte ActualType;
|
||||
public byte Red;
|
||||
public byte Green;
|
||||
@@ -133,27 +133,28 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string NameGlobalStringTag;
|
||||
public string CostGlobalStringTag;
|
||||
public float RegenPeace;
|
||||
public float RegenCombat;
|
||||
public short MaxBasePower;
|
||||
public ushort RegenInterruptTimeMS;
|
||||
public ushort Flags;
|
||||
public PowerType PowerTypeEnum;
|
||||
public sbyte MinPower;
|
||||
public short MaxBasePower;
|
||||
public sbyte CenterPower;
|
||||
public sbyte DefaultPower;
|
||||
public sbyte DisplayModifier;
|
||||
public short RegenInterruptTimeMS;
|
||||
public float RegenPeace;
|
||||
public float RegenCombat;
|
||||
public short Flags;
|
||||
}
|
||||
|
||||
public sealed class PrestigeLevelInfoRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public uint BadgeTextureFileDataID;
|
||||
public byte PrestigeLevel;
|
||||
public int PrestigeLevel;
|
||||
public int BadgeTextureFileDataID;
|
||||
public PrestigeLevelInfoFlags Flags;
|
||||
public int AwardedAchievementID;
|
||||
|
||||
public bool IsDisabled() { return Flags.HasAnyFlag(PrestigeLevelInfoFlags.Disabled); }
|
||||
public bool IsDisabled() { return (Flags & PrestigeLevelInfoFlags.Disabled) != 0; }
|
||||
}
|
||||
|
||||
public sealed class PvpDifficultyRecord
|
||||
@@ -162,10 +163,13 @@ namespace Game.DataStorage
|
||||
public byte RangeIndex;
|
||||
public byte MinLevel;
|
||||
public byte MaxLevel;
|
||||
public uint MapID;
|
||||
public ushort MapID;
|
||||
|
||||
// helpers
|
||||
public BattlegroundBracketId GetBracketId() { return (BattlegroundBracketId)RangeIndex; }
|
||||
public BattlegroundBracketId GetBracketId()
|
||||
{
|
||||
return (BattlegroundBracketId)RangeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PvpItemRecord
|
||||
@@ -175,34 +179,31 @@ namespace Game.DataStorage
|
||||
public byte ItemLevelDelta;
|
||||
}
|
||||
|
||||
public sealed class PvpRewardRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte HonorLevel;
|
||||
public byte PrestigeLevel;
|
||||
public ushort RewardPackID;
|
||||
}
|
||||
|
||||
public sealed class PvpTalentRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Description;
|
||||
public uint Id;
|
||||
public int SpecID;
|
||||
public uint SpellID;
|
||||
public uint OverridesSpellID;
|
||||
public int Flags;
|
||||
public int ActionBarSpellID;
|
||||
public int TierID;
|
||||
public byte ColumnIndex;
|
||||
public byte Flags;
|
||||
public byte ClassID;
|
||||
public ushort SpecID;
|
||||
public byte Role;
|
||||
public int PvpTalentCategoryID;
|
||||
public int LevelRequired;
|
||||
}
|
||||
|
||||
public sealed class PvpTalentUnlockRecord
|
||||
public sealed class PvpTalentCategoryRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte TierID;
|
||||
public byte ColumnIndex;
|
||||
public byte HonorLevel;
|
||||
public byte TalentSlotMask;
|
||||
}
|
||||
|
||||
public sealed class PvpTalentSlotUnlockRecord
|
||||
{
|
||||
public uint Id;
|
||||
public sbyte Slot;
|
||||
public uint LevelRequired;
|
||||
public uint DeathKnightLevelRequired;
|
||||
public uint DemonHunterLevelRequired;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ namespace Game.DataStorage
|
||||
public sealed class QuestPackageItemRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ItemID;
|
||||
public ushort PackageID;
|
||||
public QuestPackageFilter DisplayType;
|
||||
public uint ItemID;
|
||||
public byte ItemQuantity;
|
||||
public QuestPackageFilter DisplayType;
|
||||
}
|
||||
|
||||
public sealed class QuestSortRecord
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Game.DataStorage
|
||||
public sealed class RandPropPointsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int DamageReplaceStat;
|
||||
public uint[] Epic = new uint[5];
|
||||
public uint[] Superior = new uint[5];
|
||||
public uint[] Good = new uint[5];
|
||||
@@ -28,19 +29,19 @@ namespace Game.DataStorage
|
||||
public sealed class RewardPackRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint Money;
|
||||
public float ArtifactXPMultiplier;
|
||||
public byte ArtifactXPDifficulty;
|
||||
public byte ArtifactXPCategoryID;
|
||||
public ushort CharTitleID;
|
||||
public ushort TreasurePickerID;
|
||||
public uint Money;
|
||||
public byte ArtifactXPDifficulty;
|
||||
public float ArtifactXPMultiplier;
|
||||
public byte ArtifactXPCategoryID;
|
||||
public uint TreasurePickerID;
|
||||
}
|
||||
|
||||
public sealed class RewardPackXCurrencyTypeRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort CurrencyTypeID;
|
||||
public short Quantity;
|
||||
public uint CurrencyTypeID;
|
||||
public int Quantity;
|
||||
public uint RewardPackID;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,20 +21,12 @@ using System;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
public sealed class SandboxScalingRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint MinLevel;
|
||||
public uint MaxLevel;
|
||||
public uint Flags;
|
||||
}
|
||||
|
||||
public sealed class ScalingStatDistributionRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort PlayerLevelToItemLevelCurveID;
|
||||
public byte MinLevel;
|
||||
public uint MaxLevel;
|
||||
public int MinLevel;
|
||||
public int MaxLevel;
|
||||
}
|
||||
|
||||
public sealed class ScenarioRecord
|
||||
@@ -42,8 +34,9 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public ushort AreaTableID;
|
||||
public byte Flags;
|
||||
public byte Type;
|
||||
public byte Flags;
|
||||
public uint UiTextureKitID;
|
||||
}
|
||||
|
||||
public sealed class ScenarioStepRecord
|
||||
@@ -52,12 +45,14 @@ namespace Game.DataStorage
|
||||
public string Description;
|
||||
public string Title;
|
||||
public ushort ScenarioID;
|
||||
public ushort Supersedes; // Used in conjunction with Proving Grounds scenarios, when sequencing steps (Not using step order?)
|
||||
public uint CriteriaTreeId;
|
||||
public ushort 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;
|
||||
public ScenarioStepFlags Flags;
|
||||
public ushort CriteriaTreeId;
|
||||
public byte RelatedStep; // Bonus step can only be completed if scenario is in the step specified in this field
|
||||
public uint VisibilityPlayerConditionID;
|
||||
public ushort WidgetSetID;
|
||||
|
||||
// helpers
|
||||
public bool IsBonusObjective()
|
||||
@@ -95,33 +90,38 @@ namespace Game.DataStorage
|
||||
|
||||
public sealed class SkillLineRecord
|
||||
{
|
||||
public uint Id;
|
||||
public LocalizedString DisplayName;
|
||||
public string Description;
|
||||
public string AlternateVerb;
|
||||
public ushort Flags;
|
||||
public string Description;
|
||||
public string HordeDisplayName;
|
||||
public string OverrideSourceInfoDisplayName;
|
||||
public uint Id;
|
||||
public SkillCategory CategoryID;
|
||||
public byte CanLink;
|
||||
public uint SpellIconFileID;
|
||||
public byte ParentSkillLineID;
|
||||
public int SpellIconFileID;
|
||||
public sbyte CanLink;
|
||||
public uint ParentSkillLineID;
|
||||
public int ParentTierIndex;
|
||||
public ushort Flags;
|
||||
public int SpellBookSpellID;
|
||||
}
|
||||
|
||||
public sealed class SkillLineAbilityRecord
|
||||
{
|
||||
public long RaceMask;
|
||||
public ulong RaceMask;
|
||||
public uint Id;
|
||||
public uint Spell;
|
||||
public uint SupercedesSpell;
|
||||
public ushort SkillLine;
|
||||
public uint Spell;
|
||||
public short MinSkillLineRank;
|
||||
public int ClassMask;
|
||||
public uint SupercedesSpell;
|
||||
public AbilityLearnType AcquireMethod;
|
||||
public ushort TrivialSkillLineRankHigh;
|
||||
public ushort TrivialSkillLineRankLow;
|
||||
public ushort UniqueBit;
|
||||
public ushort TradeSkillCategoryID;
|
||||
public sbyte Flags;
|
||||
public byte NumSkillUps;
|
||||
public int ClassMask;
|
||||
public ushort MinSkillLineRank;
|
||||
public AbilytyLearnType AcquireMethod;
|
||||
public byte Flags;
|
||||
public short UniqueBit;
|
||||
public short TradeSkillCategoryID;
|
||||
public ushort SkillupSkillLineID;
|
||||
}
|
||||
|
||||
public sealed class SkillRaceClassInfoRecord
|
||||
@@ -129,28 +129,28 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public long RaceMask;
|
||||
public ushort SkillID;
|
||||
public SkillRaceClassInfoFlags Flags;
|
||||
public ushort SkillTierID;
|
||||
public byte Availability;
|
||||
public byte MinLevel;
|
||||
public int ClassMask;
|
||||
public SkillRaceClassInfoFlags Flags;
|
||||
public sbyte Availability;
|
||||
public sbyte MinLevel;
|
||||
public ushort SkillTierID;
|
||||
}
|
||||
|
||||
public sealed class SoundKitRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte SoundType;
|
||||
public float VolumeFloat;
|
||||
public ushort Flags;
|
||||
public float MinDistance;
|
||||
public float DistanceCutoff;
|
||||
public ushort Flags;
|
||||
public ushort SoundEntriesAdvancedID;
|
||||
public byte SoundType;
|
||||
public byte DialogType;
|
||||
public byte EAXDef;
|
||||
public uint SoundKitAdvancedID;
|
||||
public float VolumeVariationPlus;
|
||||
public float VolumeVariationMinus;
|
||||
public float PitchVariationPlus;
|
||||
public float PitchVariationMinus;
|
||||
public sbyte DialogType;
|
||||
public float PitchAdjust;
|
||||
public ushort BusOverwriteID;
|
||||
public byte MaxInstances;
|
||||
@@ -159,47 +159,38 @@ namespace Game.DataStorage
|
||||
public sealed class SpecializationSpellsRecord
|
||||
{
|
||||
public string Description;
|
||||
public uint Id;
|
||||
public ushort SpecID;
|
||||
public uint SpellID;
|
||||
public uint OverridesSpellID;
|
||||
public ushort SpecID;
|
||||
public byte DisplayOrder;
|
||||
public uint Id;
|
||||
}
|
||||
|
||||
public sealed class SpellRecord
|
||||
{
|
||||
public uint Id;
|
||||
public LocalizedString Name;
|
||||
public string NameSubtext;
|
||||
public string Description;
|
||||
public string AuraDescription;
|
||||
}
|
||||
|
||||
public sealed class SpellAuraOptionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint ProcCharges;
|
||||
public uint ProcTypeMask;
|
||||
public uint ProcCategoryRecovery;
|
||||
public ushort CumulativeAura;
|
||||
public ushort SpellProcsPerMinuteID;
|
||||
public byte DifficultyID;
|
||||
public ushort CumulativeAura;
|
||||
public uint ProcCategoryRecovery;
|
||||
public byte ProcChance;
|
||||
public uint ProcCharges;
|
||||
public ushort SpellProcsPerMinuteID;
|
||||
public int[] ProcTypeMask = new int[2];
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
public sealed class SpellAuraRestrictionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint CasterAuraSpell;
|
||||
public uint TargetAuraSpell;
|
||||
public uint ExcludeCasterAuraSpell;
|
||||
public uint ExcludeTargetAuraSpell;
|
||||
public byte DifficultyID;
|
||||
public byte CasterAuraState;
|
||||
public byte TargetAuraState;
|
||||
public byte ExcludeCasterAuraState;
|
||||
public byte ExcludeTargetAuraState;
|
||||
public uint CasterAuraSpell;
|
||||
public uint TargetAuraSpell;
|
||||
public uint ExcludeCasterAuraSpell;
|
||||
public uint ExcludeTargetAuraSpell;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
@@ -207,33 +198,33 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public int Base;
|
||||
public int Minimum;
|
||||
public short PerLevel;
|
||||
public int Minimum;
|
||||
}
|
||||
|
||||
public sealed class SpellCastingRequirementsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public ushort MinFactionID;
|
||||
public ushort RequiredAreasID;
|
||||
public ushort RequiresSpellFocus;
|
||||
public byte FacingCasterFlags;
|
||||
public byte MinReputation;
|
||||
public ushort MinFactionID;
|
||||
public sbyte MinReputation;
|
||||
public ushort RequiredAreasID;
|
||||
public byte RequiredAuraVision;
|
||||
public ushort RequiresSpellFocus;
|
||||
}
|
||||
|
||||
public sealed class SpellCategoriesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public ushort Category;
|
||||
public sbyte DefenseType;
|
||||
public sbyte DispelType;
|
||||
public sbyte Mechanic;
|
||||
public sbyte PreventionType;
|
||||
public ushort StartRecoveryCategory;
|
||||
public ushort ChargeCategory;
|
||||
public byte DifficultyID;
|
||||
public byte DefenseType;
|
||||
public byte DispelType;
|
||||
public byte Mechanic;
|
||||
public byte PreventionType;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
@@ -241,29 +232,29 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public int ChargeRecoveryTime;
|
||||
public SpellCategoryFlags Flags;
|
||||
public byte UsesPerWeek;
|
||||
public byte MaxCharges;
|
||||
public byte TypeMask;
|
||||
public int ChargeRecoveryTime;
|
||||
public int TypeMask;
|
||||
}
|
||||
|
||||
public sealed class SpellClassOptionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public FlagArray128 SpellClassMask;
|
||||
public uint ModalNextSpell;
|
||||
public byte SpellClassSet;
|
||||
public ushort ModalNextSpell;
|
||||
public FlagArray128 SpellClassMask;
|
||||
}
|
||||
|
||||
public sealed class SpellCooldownsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public uint CategoryRecoveryTime;
|
||||
public uint RecoveryTime;
|
||||
public uint StartRecoveryTime;
|
||||
public byte DifficultyID;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
@@ -271,41 +262,40 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public int Duration;
|
||||
public uint DurationPerLevel;
|
||||
public int MaxDuration;
|
||||
public int DurationPerLevel;
|
||||
}
|
||||
|
||||
public sealed class SpellEffectRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint Effect;
|
||||
public int EffectBasePoints;
|
||||
public byte EffectIndex;
|
||||
public uint EffectAura;
|
||||
public uint DifficultyID;
|
||||
public uint EffectIndex;
|
||||
public uint Effect;
|
||||
public float EffectAmplitude;
|
||||
public int EffectAttributes;
|
||||
public short EffectAura;
|
||||
public uint EffectAuraPeriod;
|
||||
public float EffectBonusCoefficient;
|
||||
public float EffectChainAmplitude;
|
||||
public int EffectChainTargets;
|
||||
public int EffectDieSides;
|
||||
public uint EffectItemType;
|
||||
public uint EffectMechanic;
|
||||
public int EffectMechanic;
|
||||
public float EffectPointsPerResource;
|
||||
public float EffectPosFacing;
|
||||
public float EffectRealPointsPerLevel;
|
||||
public uint EffectTriggerSpell;
|
||||
public float EffectPosFacing;
|
||||
public uint EffectAttributes;
|
||||
public float BonusCoefficientFromAP;
|
||||
public float PvpMultiplier;
|
||||
public float Coefficient;
|
||||
public float Variance;
|
||||
public float ResourceCoefficient;
|
||||
public float GroupSizeBasePointsCoefficient;
|
||||
public FlagArray128 EffectSpellClassMask;
|
||||
public float EffectBasePoints;
|
||||
public int[] EffectMiscValue = new int[2];
|
||||
public uint[] EffectRadiusIndex = new uint[2];
|
||||
public uint[] ImplicitTarget = new uint[2];
|
||||
public FlagArray128 EffectSpellClassMask;
|
||||
public short[] ImplicitTarget = new short[2];
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
@@ -313,9 +303,9 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public sbyte EquippedItemClass;
|
||||
public int EquippedItemInvTypes;
|
||||
public int EquippedItemSubclass;
|
||||
public sbyte EquippedItemClass;
|
||||
}
|
||||
|
||||
public sealed class SpellFocusObjectRecord
|
||||
@@ -328,7 +318,7 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public ushort InterruptFlags;
|
||||
public short InterruptFlags;
|
||||
public uint[] AuraInterruptFlags = new uint[2];
|
||||
public uint[] ChannelInterruptFlags = new uint[2];
|
||||
public uint SpellID;
|
||||
@@ -338,10 +328,12 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public string HordeName;
|
||||
public uint[] EffectArg = new uint[ItemConst.MaxItemEnchantmentEffects];
|
||||
public float[] EffectScalingPoints = new float[ItemConst.MaxItemEnchantmentEffects];
|
||||
public uint TransmogCost;
|
||||
public uint IconFileDataID;
|
||||
public uint TransmogPlayerConditionID;
|
||||
public ushort[] EffectPointsMin = new ushort[ItemConst.MaxItemEnchantmentEffects];
|
||||
public ushort ItemVisual;
|
||||
public EnchantmentSlotMask Flags;
|
||||
@@ -350,19 +342,18 @@ namespace Game.DataStorage
|
||||
public ushort ItemLevel;
|
||||
public byte Charges;
|
||||
public ItemEnchantmentType[] Effect = new ItemEnchantmentType[ItemConst.MaxItemEnchantmentEffects];
|
||||
public sbyte ScalingClass;
|
||||
public sbyte ScalingClassRestricted;
|
||||
public byte ConditionID;
|
||||
public byte MinLevel;
|
||||
public byte MaxLevel;
|
||||
public sbyte ScalingClass;
|
||||
public sbyte ScalingClassRestricted;
|
||||
public ushort TransmogPlayerConditionID;
|
||||
}
|
||||
|
||||
public sealed class SpellItemEnchantmentConditionRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint[] LtOperand = new uint[5];
|
||||
public byte[] LtOperandType = new byte[5];
|
||||
public uint[] LtOperand = new uint[5];
|
||||
public byte[] Operator = new byte[5];
|
||||
public byte[] RtOperandType = new byte[5];
|
||||
public byte[] RtOperand = new byte[5];
|
||||
@@ -380,10 +371,10 @@ namespace Game.DataStorage
|
||||
public sealed class SpellLevelsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public ushort BaseLevel;
|
||||
public ushort MaxLevel;
|
||||
public ushort SpellLevel;
|
||||
public byte DifficultyID;
|
||||
public byte MaxPassiveAuraLevel;
|
||||
public uint SpellID;
|
||||
}
|
||||
@@ -391,43 +382,50 @@ namespace Game.DataStorage
|
||||
public sealed class SpellMiscRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public ushort CastingTimeIndex;
|
||||
public ushort DurationIndex;
|
||||
public ushort RangeIndex;
|
||||
public byte SchoolMask;
|
||||
public uint SpellIconFileDataID;
|
||||
public float Speed;
|
||||
public uint ActiveIconFileDataID;
|
||||
public float LaunchDelay;
|
||||
public byte DifficultyID;
|
||||
public uint[] Attributes = new uint[14];
|
||||
public float MinDuration;
|
||||
public uint SpellIconFileDataID;
|
||||
public uint ActiveIconFileDataID;
|
||||
public int[] Attributes = new int[14];
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
public sealed class SpellNameRecord
|
||||
{
|
||||
public uint Id; // SpellID
|
||||
public LocalizedString Name;
|
||||
}
|
||||
|
||||
public sealed class SpellPowerRecord
|
||||
{
|
||||
public int ManaCost;
|
||||
public float PowerCostPct;
|
||||
public float PowerPctPerSecond;
|
||||
public uint RequiredAuraSpellID;
|
||||
public float PowerCostMaxPct;
|
||||
public byte OrderIndex;
|
||||
public PowerType PowerType;
|
||||
public uint Id;
|
||||
public byte ManaCostPerLevel;
|
||||
public ushort ManaPerSecond;
|
||||
public int OptionalCost; // Spell uses [ManaCost, ManaCost+ManaCostAdditional] power - affects tooltip parsing as multiplier on SpellEffectEntry::EffectPointsPerResource
|
||||
// only SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE, SPELL_EFFECT_WEAPON_DAMAGE, SPELL_EFFECT_NORMALIZED_WEAPON_DMG
|
||||
public byte OrderIndex;
|
||||
public int ManaCost;
|
||||
public int ManaCostPerLevel;
|
||||
public int ManaPerSecond;
|
||||
public uint PowerDisplayID;
|
||||
public uint AltPowerBarID;
|
||||
public int AltPowerBarID;
|
||||
public float PowerCostPct;
|
||||
public float PowerCostMaxPct;
|
||||
public float PowerPctPerSecond;
|
||||
public PowerType PowerType;
|
||||
public uint RequiredAuraSpellID;
|
||||
public uint OptionalCost; // Spell uses [ManaCost, ManaCost+ManaCostAdditional] power - affects tooltip parsing as multiplier on SpellEffectEntry::EffectPointsPerResource
|
||||
// only SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE, SPELL_EFFECT_WEAPON_DAMAGE, SPELL_EFFECT_NORMALIZED_WEAPON_DMG
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
public sealed class SpellPowerDifficultyRecord
|
||||
{
|
||||
public uint Id;
|
||||
public byte DifficultyID;
|
||||
public byte OrderIndex;
|
||||
public uint Id;
|
||||
}
|
||||
|
||||
public sealed class SpellProcsPerMinuteRecord
|
||||
@@ -440,10 +438,10 @@ namespace Game.DataStorage
|
||||
public sealed class SpellProcsPerMinuteModRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float Coeff;
|
||||
public ushort Param;
|
||||
public SpellProcsPerMinuteModType Type;
|
||||
public uint SpellProcsPerMinuteID;
|
||||
public ushort Param;
|
||||
public float Coeff;
|
||||
public ushort SpellProcsPerMinuteID;
|
||||
}
|
||||
|
||||
public sealed class SpellRadiusRecord
|
||||
@@ -460,9 +458,9 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string DisplayName;
|
||||
public string DisplayNameShort;
|
||||
public SpellRangeFlag Flags;
|
||||
public float[] RangeMin = new float[2];
|
||||
public float[] RangeMax = new float[2];
|
||||
public SpellRangeFlag Flags;
|
||||
}
|
||||
|
||||
public sealed class SpellReagentsRecord
|
||||
@@ -477,46 +475,46 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public ushort ScalesFromItemLevel;
|
||||
public sbyte Class;
|
||||
public byte MinScalingLevel;
|
||||
public int Class;
|
||||
public uint MinScalingLevel;
|
||||
public uint MaxScalingLevel;
|
||||
public ushort ScalesFromItemLevel;
|
||||
}
|
||||
|
||||
public sealed class SpellShapeshiftRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public sbyte StanceBarOrder;
|
||||
public uint[] ShapeshiftExclude = new uint[2];
|
||||
public uint[] ShapeshiftMask = new uint[2];
|
||||
public byte StanceBarOrder;
|
||||
}
|
||||
|
||||
public sealed class SpellShapeshiftFormRecord
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public float DamageVariance;
|
||||
public SpellShapeshiftFormFlags Flags;
|
||||
public ushort CombatRoundTime;
|
||||
public ushort MountTypeID;
|
||||
public sbyte CreatureType;
|
||||
public byte BonusActionBar;
|
||||
public uint AttackIconFileID;
|
||||
public ushort[] CreatureDisplayID = new ushort[4];
|
||||
public ushort[] PresetSpellID = new ushort[SpellConst.MaxShapeshift];
|
||||
public SpellShapeshiftFormFlags Flags;
|
||||
public int AttackIconFileID;
|
||||
public sbyte BonusActionBar;
|
||||
public ushort CombatRoundTime;
|
||||
public float DamageVariance;
|
||||
public ushort MountTypeID;
|
||||
public uint[] CreatureDisplayID = new uint[4];
|
||||
public uint[] PresetSpellID = new uint[SpellConst.MaxShapeshift];
|
||||
}
|
||||
|
||||
public sealed class SpellTargetRestrictionsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public float ConeDegrees;
|
||||
public float Width;
|
||||
public uint Targets;
|
||||
public ushort TargetCreatureType;
|
||||
public byte DifficultyID;
|
||||
public float ConeDegrees;
|
||||
public byte MaxTargets;
|
||||
public uint MaxTargetLevel;
|
||||
public ushort TargetCreatureType;
|
||||
public int Targets;
|
||||
public float Width;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
@@ -524,34 +522,34 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public uint SpellID;
|
||||
public uint[] Totem = new uint[SpellConst.MaxTotems];
|
||||
public ushort[] RequiredTotemCategoryID = new ushort[SpellConst.MaxTotems];
|
||||
public uint[] Totem = new uint[SpellConst.MaxTotems];
|
||||
}
|
||||
|
||||
public sealed class SpellXSpellVisualRecord
|
||||
{
|
||||
public uint SpellVisualID;
|
||||
public uint Id;
|
||||
public float Probability;
|
||||
public ushort CasterPlayerConditionID;
|
||||
public ushort CasterUnitConditionID;
|
||||
public ushort ViewerPlayerConditionID;
|
||||
public ushort ViewerUnitConditionID;
|
||||
public uint SpellIconFileID;
|
||||
public uint ActiveIconFileID;
|
||||
public byte Flags;
|
||||
public byte DifficultyID;
|
||||
public uint SpellVisualID;
|
||||
public float Probability;
|
||||
public byte Flags;
|
||||
public byte Priority;
|
||||
public int SpellIconFileID;
|
||||
public int ActiveIconFileID;
|
||||
public ushort ViewerUnitConditionID;
|
||||
public uint ViewerPlayerConditionID;
|
||||
public ushort CasterUnitConditionID;
|
||||
public uint CasterPlayerConditionID;
|
||||
public uint SpellID;
|
||||
}
|
||||
|
||||
public sealed class SummonPropertiesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public SummonPropFlags Flags;
|
||||
public SummonCategory Control;
|
||||
public ushort Faction;
|
||||
public uint Faction;
|
||||
public SummonType Title;
|
||||
public sbyte Slot;
|
||||
public int Slot;
|
||||
public SummonPropFlags Flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,48 +30,49 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public string Description;
|
||||
public byte TierID;
|
||||
public byte Flags;
|
||||
public byte ColumnIndex;
|
||||
public byte ClassID;
|
||||
public ushort SpecID;
|
||||
public uint SpellID;
|
||||
public uint OverridesSpellID;
|
||||
public ushort SpecID;
|
||||
public byte TierID;
|
||||
public byte ColumnIndex;
|
||||
public byte Flags;
|
||||
public byte[] CategoryMask = new byte[2];
|
||||
public byte ClassID;
|
||||
}
|
||||
|
||||
public sealed class TaxiNodesRecord
|
||||
{
|
||||
public uint Id;
|
||||
public LocalizedString Name;
|
||||
public Vector3 Pos;
|
||||
public uint[] MountCreatureID = new uint[2];
|
||||
public Vector2 MapOffset;
|
||||
public float Facing;
|
||||
public Vector2 FlightMapOffset;
|
||||
public uint Id;
|
||||
public ushort ContinentID;
|
||||
public ushort ConditionID;
|
||||
public ushort CharacterBitNumber;
|
||||
public TaxiNodeFlags Flags;
|
||||
public int UiTextureKitID;
|
||||
public float Facing;
|
||||
public uint SpecialIconConditionID;
|
||||
public uint VisibilityConditionID;
|
||||
public uint[] MountCreatureID = new uint[2];
|
||||
}
|
||||
|
||||
public sealed class TaxiPathRecord
|
||||
{
|
||||
public uint Id;
|
||||
public ushort FromTaxiNode;
|
||||
public ushort ToTaxiNode;
|
||||
public uint Id;
|
||||
public uint Cost;
|
||||
}
|
||||
|
||||
public sealed class TaxiPathNodeRecord
|
||||
{
|
||||
public Vector3 Loc;
|
||||
public ushort PathID;
|
||||
public ushort ContinentID;
|
||||
public byte NodeIndex;
|
||||
public uint Id;
|
||||
public ushort PathID;
|
||||
public uint NodeIndex;
|
||||
public ushort ContinentID;
|
||||
public TaxiPathNodeFlags Flags;
|
||||
public uint Delay;
|
||||
public ushort ArrivalEventID;
|
||||
@@ -82,17 +83,17 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public string Name;
|
||||
public uint TotemCategoryMask;
|
||||
public byte TotemCategoryType;
|
||||
public int TotemCategoryMask;
|
||||
}
|
||||
|
||||
public sealed class ToyRecord
|
||||
{
|
||||
public string SourceText;
|
||||
public uint Id;
|
||||
public uint ItemID;
|
||||
public byte Flags;
|
||||
public byte SourceTypeEnum;
|
||||
public uint Id;
|
||||
public sbyte SourceTypeEnum;
|
||||
}
|
||||
|
||||
public sealed class TransmogHolidayRecord
|
||||
@@ -104,15 +105,15 @@ namespace Game.DataStorage
|
||||
public sealed class TransmogSetRecord
|
||||
{
|
||||
public string Name;
|
||||
public ushort ParentTransmogSetID;
|
||||
public ushort UIOrder;
|
||||
public byte ExpansionID;
|
||||
public uint Id;
|
||||
public byte Flags;
|
||||
public int TrackingQuestID;
|
||||
public int ClassMask;
|
||||
public uint TrackingQuestID;
|
||||
public int Flags;
|
||||
public uint TransmogSetGroupID;
|
||||
public int ItemNameDescriptionID;
|
||||
public byte TransmogSetGroupID;
|
||||
public ushort ParentTransmogSetID;
|
||||
public byte ExpansionID;
|
||||
public short UiOrder;
|
||||
}
|
||||
|
||||
public sealed class TransmogSetGroupRecord
|
||||
@@ -132,17 +133,18 @@ namespace Game.DataStorage
|
||||
public sealed class TransportAnimationRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint TimeIndex;
|
||||
public Vector3 Pos;
|
||||
public byte SequenceID;
|
||||
public uint TimeIndex;
|
||||
public uint TransportID;
|
||||
}
|
||||
|
||||
public sealed class TransportRotationRecord
|
||||
{
|
||||
public uint Id;
|
||||
public uint TimeIndex;
|
||||
public float[] Rot = new float[4];
|
||||
public uint TimeIndex;
|
||||
public uint GameObjectsID;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,60 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
using Framework.GameMath;
|
||||
using Framework.Constants;
|
||||
|
||||
namespace Game.DataStorage
|
||||
{
|
||||
public sealed class UiMapRecord
|
||||
{
|
||||
public LocalizedString Name;
|
||||
public uint Id;
|
||||
public int ParentUiMapID;
|
||||
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 sealed class UiMapAssignmentRecord
|
||||
{
|
||||
public Vector2 UiMin;
|
||||
public Vector2 UiMax;
|
||||
public Vector3[] Region = new Vector3[2];
|
||||
public uint Id;
|
||||
public int UiMapID;
|
||||
public int OrderIndex;
|
||||
public int MapID;
|
||||
public int AreaID;
|
||||
public int WmoDoodadPlacementID;
|
||||
public int WmoGroupID;
|
||||
}
|
||||
|
||||
public sealed class UiMapLinkRecord
|
||||
{
|
||||
public Vector2 UiMin;
|
||||
public Vector2 UiMax;
|
||||
public uint Id;
|
||||
public int ParentUiMapID;
|
||||
public int OrderIndex;
|
||||
public int ChildUiMapID;
|
||||
}
|
||||
|
||||
public sealed class UiMapXMapArtRecord
|
||||
{
|
||||
public uint Id;
|
||||
public int PhaseID;
|
||||
public int UiMapArtID;
|
||||
public int UiMapID;
|
||||
}
|
||||
|
||||
public sealed class UnitPowerBarRecord
|
||||
{
|
||||
public uint Id;
|
||||
@@ -24,17 +75,17 @@ namespace Game.DataStorage
|
||||
public string Cost;
|
||||
public string OutOfError;
|
||||
public string ToolTip;
|
||||
public uint MinPower;
|
||||
public uint MaxPower;
|
||||
public ushort StartPower;
|
||||
public byte CenterPower;
|
||||
public float RegenerationPeace;
|
||||
public float RegenerationCombat;
|
||||
public uint[] FileDataID = new uint[6];
|
||||
public uint[] Color = new uint[6];
|
||||
public byte BarType;
|
||||
public ushort Flags;
|
||||
public float StartInset;
|
||||
public float EndInset;
|
||||
public ushort StartPower;
|
||||
public ushort Flags;
|
||||
public byte CenterPower;
|
||||
public byte BarType;
|
||||
public byte MinPower;
|
||||
public uint MaxPower;
|
||||
public uint[] FileDataID = new uint[6];
|
||||
public uint[] Color = new uint[6];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Game.DataStorage
|
||||
{
|
||||
public uint Id;
|
||||
public VehicleFlags Flags;
|
||||
public byte FlagsB;
|
||||
public float TurnSpeed;
|
||||
public float PitchSpeed;
|
||||
public float PitchMin;
|
||||
@@ -36,21 +37,22 @@ namespace Game.DataStorage
|
||||
public float FacingLimitRight;
|
||||
public float FacingLimitLeft;
|
||||
public float CameraYawOffset;
|
||||
public ushort[] SeatID = new ushort[SharedConst.MaxVehicleSeats];
|
||||
public ushort VehicleUIIndicatorID;
|
||||
public ushort[] PowerDisplayID = new ushort[3];
|
||||
public byte FlagsB;
|
||||
public byte UiLocomotionType;
|
||||
public ushort MissileTargetingID;
|
||||
public ushort VehicleUIIndicatorID;
|
||||
public int MissileTargetingID;
|
||||
public ushort[] SeatID = new ushort[8];
|
||||
public ushort[] PowerDisplayID = new ushort[3];
|
||||
}
|
||||
|
||||
public sealed class VehicleSeatRecord
|
||||
{
|
||||
public uint Id;
|
||||
public Vector3 AttachmentOffset;
|
||||
public Vector3 CameraOffset;
|
||||
public VehicleSeatFlags Flags;
|
||||
public VehicleSeatFlagsB FlagsB;
|
||||
public uint FlagsC;
|
||||
public Vector3 AttachmentOffset;
|
||||
public int FlagsC;
|
||||
public sbyte AttachmentID;
|
||||
public float EnterPreDelay;
|
||||
public float EnterSpeed;
|
||||
public float EnterGravity;
|
||||
@@ -58,6 +60,12 @@ namespace Game.DataStorage
|
||||
public float EnterMaxDuration;
|
||||
public float EnterMinArcHeight;
|
||||
public float EnterMaxArcHeight;
|
||||
public int EnterAnimStart;
|
||||
public int EnterAnimLoop;
|
||||
public int RideAnimStart;
|
||||
public int RideAnimLoop;
|
||||
public int RideUpperAnimStart;
|
||||
public int RideUpperAnimLoop;
|
||||
public float ExitPreDelay;
|
||||
public float ExitSpeed;
|
||||
public float ExitGravity;
|
||||
@@ -65,49 +73,41 @@ namespace Game.DataStorage
|
||||
public float ExitMaxDuration;
|
||||
public float ExitMinArcHeight;
|
||||
public float ExitMaxArcHeight;
|
||||
public int ExitAnimStart;
|
||||
public int ExitAnimLoop;
|
||||
public int ExitAnimEnd;
|
||||
public short VehicleEnterAnim;
|
||||
public sbyte VehicleEnterAnimBone;
|
||||
public short VehicleExitAnim;
|
||||
public sbyte VehicleExitAnimBone;
|
||||
public short VehicleRideAnimLoop;
|
||||
public sbyte VehicleRideAnimLoopBone;
|
||||
public sbyte PassengerAttachmentID;
|
||||
public float PassengerYaw;
|
||||
public float PassengerPitch;
|
||||
public float PassengerRoll;
|
||||
public float VehicleEnterAnimDelay;
|
||||
public float VehicleExitAnimDelay;
|
||||
public sbyte VehicleAbilityDisplay;
|
||||
public uint EnterUISoundID;
|
||||
public uint ExitUISoundID;
|
||||
public int UiSkinFileDataID;
|
||||
public float CameraEnteringDelay;
|
||||
public float CameraEnteringDuration;
|
||||
public float CameraExitingDelay;
|
||||
public float CameraExitingDuration;
|
||||
public Vector3 CameraOffset;
|
||||
public float CameraPosChaseRate;
|
||||
public float CameraFacingChaseRate;
|
||||
public float CameraEnteringZoom;
|
||||
public float CameraSeatZoomMin;
|
||||
public float CameraSeatZoomMax;
|
||||
public uint UiSkinFileDataID;
|
||||
public short EnterAnimStart;
|
||||
public short EnterAnimLoop;
|
||||
public short RideAnimStart;
|
||||
public short RideAnimLoop;
|
||||
public short RideUpperAnimStart;
|
||||
public short RideUpperAnimLoop;
|
||||
public short ExitAnimStart;
|
||||
public short ExitAnimLoop;
|
||||
public short ExitAnimEnd;
|
||||
public short VehicleEnterAnim;
|
||||
public short VehicleExitAnim;
|
||||
public short VehicleRideAnimLoop;
|
||||
public ushort EnterAnimKitID;
|
||||
public ushort RideAnimKitID;
|
||||
public ushort ExitAnimKitID;
|
||||
public ushort VehicleEnterAnimKitID;
|
||||
public ushort VehicleRideAnimKitID;
|
||||
public ushort VehicleExitAnimKitID;
|
||||
public ushort CameraModeID;
|
||||
public sbyte AttachmentID;
|
||||
public sbyte PassengerAttachmentID;
|
||||
public sbyte VehicleEnterAnimBone;
|
||||
public sbyte VehicleExitAnimBone;
|
||||
public sbyte VehicleRideAnimLoopBone;
|
||||
public byte VehicleAbilityDisplay;
|
||||
public uint EnterUISoundID;
|
||||
public ushort ExitUISoundID;
|
||||
public short EnterAnimKitID;
|
||||
public short RideAnimKitID;
|
||||
public short ExitAnimKitID;
|
||||
public short VehicleEnterAnimKitID;
|
||||
public short VehicleRideAnimKitID;
|
||||
public short VehicleExitAnimKitID;
|
||||
public short CameraModeID;
|
||||
|
||||
public bool CanEnterOrExit()
|
||||
{
|
||||
@@ -115,7 +115,7 @@ namespace Game.DataStorage
|
||||
//If it has anmation for enter/ride, means it can be entered/exited by logic
|
||||
Flags.HasAnyFlag(VehicleSeatFlags.HasLowerAnimForEnter | VehicleSeatFlags.HasLowerAnimForRide));
|
||||
}
|
||||
public bool CanSwitchFromSeat() { return Flags.HasAnyFlag(VehicleSeatFlags.CanSwitch); }
|
||||
public bool CanSwitchFromSeat() { return (Flags & VehicleSeatFlags.CanSwitch) != 0; }
|
||||
public bool IsUsableByOverride()
|
||||
{
|
||||
return Flags.HasAnyFlag(VehicleSeatFlags.Uncontrolled | VehicleSeatFlags.Unk18)
|
||||
|
||||
@@ -23,87 +23,48 @@ namespace Game.DataStorage
|
||||
public sealed class WMOAreaTableRecord
|
||||
{
|
||||
public string AreaName;
|
||||
public uint Id;
|
||||
public ushort WmoID; // used in root WMO
|
||||
public byte NameSetID; // used in adt file
|
||||
public int WmoGroupID; // used in group WMO
|
||||
public ushort AmbienceID;
|
||||
public ushort ZoneMusic;
|
||||
public ushort IntroSound;
|
||||
public ushort AreaTableID;
|
||||
public ushort UwIntroSound;
|
||||
public ushort UwAmbience;
|
||||
public sbyte NameSetID; // used in adt file
|
||||
public byte SoundProviderPref;
|
||||
public byte SoundProviderPrefUnderwater;
|
||||
public ushort AmbienceID;
|
||||
public ushort UwAmbience;
|
||||
public ushort ZoneMusic;
|
||||
public uint UwZoneMusic;
|
||||
public ushort IntroSound;
|
||||
public ushort UwIntroSound;
|
||||
public ushort AreaTableID;
|
||||
public byte Flags;
|
||||
public uint Id;
|
||||
public byte UwZoneMusic;
|
||||
public uint WmoID; // used in root WMO
|
||||
}
|
||||
|
||||
public sealed class WorldEffectRecord
|
||||
{
|
||||
public uint ID;
|
||||
public uint TargetAsset;
|
||||
public ushort CombatConditionID;
|
||||
public byte TargetType;
|
||||
public byte WhenToDisplay;
|
||||
public uint QuestFeedbackEffectID;
|
||||
public ushort PlayerConditionID;
|
||||
}
|
||||
|
||||
public sealed class WorldMapAreaRecord
|
||||
{
|
||||
public string AreaName;
|
||||
public float LocLeft;
|
||||
public float LocRight;
|
||||
public float LocTop;
|
||||
public float LocBottom;
|
||||
public uint Flags;
|
||||
public ushort MapID;
|
||||
public ushort AreaID;
|
||||
public short DisplayMapID;
|
||||
public short DefaultDungeonFloor;
|
||||
public ushort ParentWorldMapID;
|
||||
public byte LevelRangeMin;
|
||||
public byte LevelRangeMax;
|
||||
public byte BountySetID;
|
||||
public byte BountyDisplayLocation;
|
||||
public uint Id;
|
||||
public uint VisibilityPlayerConditionID;
|
||||
public uint QuestFeedbackEffectID;
|
||||
public byte WhenToDisplay;
|
||||
public byte TargetType;
|
||||
public int TargetAsset;
|
||||
public uint PlayerConditionID;
|
||||
public ushort CombatConditionID;
|
||||
}
|
||||
|
||||
public sealed class WorldMapOverlayRecord
|
||||
{
|
||||
public string TextureName;
|
||||
public uint Id;
|
||||
public uint UiMapArtID;
|
||||
public ushort TextureWidth;
|
||||
public ushort TextureHeight;
|
||||
public ushort MapAreaID; // idx in WorldMapArea.dbc
|
||||
public ushort OffsetX;
|
||||
public uint OffsetY;
|
||||
public ushort HitRectTop;
|
||||
public ushort HitRectLeft;
|
||||
public ushort HitRectBottom;
|
||||
public ushort HitRectRight;
|
||||
public ushort PlayerConditionID;
|
||||
public byte Flags;
|
||||
public uint[] AreaID = new uint[SharedConst.MaxWorldMapOverlayArea]; // needs checked
|
||||
|
||||
}
|
||||
|
||||
public sealed class WorldMapTransformsRecord
|
||||
{
|
||||
public uint Id;
|
||||
public Vector3 RegionMin;
|
||||
public Vector3 RegionMax;
|
||||
public Vector2 RegionOffset;
|
||||
public float RegionScale;
|
||||
public ushort MapID;
|
||||
public ushort AreaID;
|
||||
public ushort NewMapID;
|
||||
public ushort NewDungeonMapID;
|
||||
public ushort NewAreaID;
|
||||
public byte Flags;
|
||||
public int Priority;
|
||||
public int OffsetX;
|
||||
public int OffsetY;
|
||||
public int HitRectTop;
|
||||
public int HitRectBottom;
|
||||
public int HitRectLeft;
|
||||
public int HitRectRight;
|
||||
public uint PlayerConditionID;
|
||||
public uint Flags;
|
||||
public uint[] AreaID = new uint[SharedConst.MaxWorldMapOverlayArea];
|
||||
}
|
||||
|
||||
public sealed class WorldSafeLocsRecord
|
||||
@@ -111,7 +72,7 @@ namespace Game.DataStorage
|
||||
public uint Id;
|
||||
public string AreaName;
|
||||
public Vector3 Loc;
|
||||
public float Facing;
|
||||
public ushort MapID;
|
||||
public float Facing;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2156,7 +2156,7 @@ namespace Game.DungeonFinding
|
||||
minlevel = dbc.MinLevel;
|
||||
maxlevel = dbc.MaxLevel;
|
||||
difficulty = dbc.DifficultyID;
|
||||
seasonal = dbc.Flags.HasAnyFlag(LfgFlags.Seasonal);
|
||||
seasonal = dbc.Flags[0].HasAnyFlag(LfgFlags.Seasonal);
|
||||
}
|
||||
|
||||
public uint id;
|
||||
|
||||
@@ -39,7 +39,8 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.AreaTrigger;
|
||||
objectTypeId = TypeId.AreaTrigger;
|
||||
|
||||
m_updateFlag = UpdateFlag.StationaryPosition | UpdateFlag.Areatrigger;
|
||||
m_updateFlag.Stationary = true;
|
||||
m_updateFlag.AreaTrigger = true;
|
||||
|
||||
valuesCount = (int)AreaTriggerFields.End;
|
||||
|
||||
@@ -142,7 +143,7 @@ namespace Game.Entities
|
||||
{
|
||||
AreaTriggerCircularMovementInfo cmi = GetMiscTemplate().CircularMovementInfo;
|
||||
if (target && GetTemplate().HasFlag(AreaTriggerFlags.HasAttached))
|
||||
cmi.TargetGUID.Set(target.GetGUID());
|
||||
cmi.PathTarget.Set(target.GetGUID());
|
||||
else
|
||||
cmi.Center.Set(new Vector3(pos.posX, pos.posY, pos.posZ));
|
||||
|
||||
@@ -624,12 +625,12 @@ namespace Game.Entities
|
||||
{
|
||||
if (_reachedDestination)
|
||||
{
|
||||
AreaTriggerReShape reshapeDest = new AreaTriggerReShape();
|
||||
AreaTriggerRePath reshapeDest = new AreaTriggerRePath();
|
||||
reshapeDest.TriggerGUID = GetGUID();
|
||||
SendMessageToSet(reshapeDest, true);
|
||||
}
|
||||
|
||||
AreaTriggerReShape reshape = new AreaTriggerReShape();
|
||||
AreaTriggerRePath reshape = new AreaTriggerRePath();
|
||||
reshape.TriggerGUID = GetGUID();
|
||||
reshape.AreaTriggerSpline.HasValue = true;
|
||||
reshape.AreaTriggerSpline.Value.ElapsedTimeForMovement = GetElapsedTimeForMovement();
|
||||
@@ -644,7 +645,7 @@ namespace Game.Entities
|
||||
void InitCircularMovement(AreaTriggerCircularMovementInfo cmi, uint timeToTarget)
|
||||
{
|
||||
// Circular movement requires either a center position or an attached unit
|
||||
Cypher.Assert(cmi.Center.HasValue || cmi.TargetGUID.HasValue);
|
||||
Cypher.Assert(cmi.Center.HasValue || cmi.PathTarget.HasValue);
|
||||
|
||||
// should be sent in object create packets only
|
||||
updateValues[(int)AreaTriggerFields.TimeToTarget].UnsignedValue = timeToTarget;
|
||||
@@ -656,7 +657,7 @@ namespace Game.Entities
|
||||
|
||||
if (IsInWorld)
|
||||
{
|
||||
AreaTriggerReShape reshape = new AreaTriggerReShape();
|
||||
AreaTriggerRePath reshape = new AreaTriggerRePath();
|
||||
reshape.TriggerGUID = GetGUID();
|
||||
reshape.AreaTriggerCircularMovement = _circularMovementInfo;
|
||||
|
||||
@@ -671,12 +672,12 @@ namespace Game.Entities
|
||||
|
||||
Position GetCircularMovementCenterPosition()
|
||||
{
|
||||
if (_circularMovementInfo.HasValue)
|
||||
if (!_circularMovementInfo.HasValue)
|
||||
return null;
|
||||
|
||||
if (_circularMovementInfo.Value.TargetGUID.HasValue)
|
||||
if (_circularMovementInfo.Value.PathTarget.HasValue)
|
||||
{
|
||||
WorldObject center = Global.ObjAccessor.GetWorldObject(this, _circularMovementInfo.Value.TargetGUID.Value);
|
||||
WorldObject center = Global.ObjAccessor.GetWorldObject(this, _circularMovementInfo.Value.PathTarget.Value);
|
||||
if (center)
|
||||
return center;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ namespace Game.Entities
|
||||
{
|
||||
public void Write(WorldPacket data)
|
||||
{
|
||||
data.WriteBit(TargetGUID.HasValue);
|
||||
data.WriteBit(PathTarget.HasValue);
|
||||
data.WriteBit(Center.HasValue);
|
||||
data.WriteBit(CounterClockwise);
|
||||
data.WriteBit(CanLoop);
|
||||
@@ -133,14 +133,14 @@ namespace Game.Entities
|
||||
data.WriteFloat(InitialAngle);
|
||||
data.WriteFloat(ZOffset);
|
||||
|
||||
if (TargetGUID.HasValue)
|
||||
data.WritePackedGuid(TargetGUID.Value);
|
||||
if (PathTarget.HasValue)
|
||||
data.WritePackedGuid(PathTarget.Value);
|
||||
|
||||
if (Center.HasValue)
|
||||
data.WriteVector3(Center.Value);
|
||||
}
|
||||
|
||||
public Optional<ObjectGuid> TargetGUID;
|
||||
public Optional<ObjectGuid> PathTarget;
|
||||
public Optional<Vector3> Center;
|
||||
public bool CounterClockwise;
|
||||
public bool CanLoop;
|
||||
@@ -228,6 +228,9 @@ namespace Game.Entities
|
||||
public uint MorphCurveId;
|
||||
public uint FacingCurveId;
|
||||
|
||||
public uint AnimId;
|
||||
public uint AnimKitId;
|
||||
|
||||
public uint DecalPropertiesId;
|
||||
|
||||
public uint TimeToTarget;
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.Conversation;
|
||||
objectTypeId = TypeId.Conversation;
|
||||
|
||||
m_updateFlag = UpdateFlag.StationaryPosition;
|
||||
m_updateFlag.Stationary = true;
|
||||
m_updateFlag.Conversation = true;
|
||||
|
||||
valuesCount = (int)ConversationFields.End;
|
||||
_dynamicValuesCount = (int)ConversationDynamicFields.End;
|
||||
@@ -118,6 +119,7 @@ namespace Game.Entities
|
||||
|
||||
SetUInt32Value(ConversationFields.LastLineEndTime, conversationTemplate.LastLineEndTime);
|
||||
_duration = conversationTemplate.LastLineEndTime;
|
||||
_textureKitId = conversationTemplate.TextureKitId;
|
||||
|
||||
for (ushort actorIndex = 0; actorIndex < conversationTemplate.Actors.Count; ++actorIndex)
|
||||
{
|
||||
@@ -125,7 +127,8 @@ namespace Game.Entities
|
||||
if (actor != null)
|
||||
{
|
||||
ConversationDynamicFieldActor actorField = new ConversationDynamicFieldActor();
|
||||
actorField.ActorTemplate = actor;
|
||||
actorField.ActorTemplate.CreatureId = actor.CreatureId;
|
||||
actorField.ActorTemplate.CreatureModelId = actor.CreatureModelId;
|
||||
actorField.Type = ConversationDynamicFieldActor.ActorType.CreatureActor;
|
||||
SetDynamicStructuredValue(ConversationDynamicFields.Actors, actorIndex, actorField);
|
||||
}
|
||||
@@ -189,6 +192,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
uint GetDuration() { return _duration; }
|
||||
public uint GetTextureKitId() { return _textureKitId; }
|
||||
|
||||
public ObjectGuid GetCreatorGuid() { return _creatorGuid; }
|
||||
|
||||
@@ -201,6 +205,7 @@ namespace Game.Entities
|
||||
Position _stationaryPosition = new Position();
|
||||
ObjectGuid _creatorGuid;
|
||||
uint _duration;
|
||||
uint _textureKitId;
|
||||
List<ObjectGuid> _participants = new List<ObjectGuid>();
|
||||
}
|
||||
|
||||
@@ -218,7 +223,13 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public ObjectGuid ActorGuid;
|
||||
public ConversationActorTemplate ActorTemplate;
|
||||
public ActorTemplateStruct ActorTemplate;
|
||||
|
||||
public struct ActorTemplateStruct
|
||||
{
|
||||
public uint CreatureId;
|
||||
public uint CreatureModelId;
|
||||
}
|
||||
|
||||
public ActorType Type;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Game.Entities
|
||||
objectTypeId = TypeId.Corpse;
|
||||
objectTypeMask |= TypeMask.Corpse;
|
||||
|
||||
m_updateFlag = UpdateFlag.StationaryPosition;
|
||||
m_updateFlag.Stationary = true;
|
||||
|
||||
valuesCount = (int)CorpseFields.End;
|
||||
|
||||
|
||||
@@ -141,6 +141,10 @@ namespace Game.Entities
|
||||
if (setSpawnTime)
|
||||
m_respawnTime = Time.UnixTime + respawnDelay;
|
||||
|
||||
// if corpse was removed during falling, the falling will continue and override relocation to respawn position
|
||||
if (IsFalling())
|
||||
StopMoving();
|
||||
|
||||
float x, y, z, o;
|
||||
GetRespawnPosition(out x, out y, out z, out o);
|
||||
SetHomePosition(x, y, z, o);
|
||||
@@ -193,22 +197,22 @@ namespace Game.Entities
|
||||
SetByteValue(UnitFields.Bytes0, 1, (byte)cinfo.UnitClass);
|
||||
|
||||
// Cancel load if no model defined
|
||||
if (cinfo.GetFirstValidModelId() == 0)
|
||||
if (cinfo.GetFirstValidModel() == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has no model defined in table `creature_template`, can't load. ", entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint displayID = ObjectManager.ChooseDisplayId(GetCreatureTemplate(), data);
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
|
||||
CreatureModel model = ObjectManager.ChooseDisplayId(cinfo, data);
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref model, cinfo);
|
||||
if (minfo == null) // Cancel load if no model defined
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has no model defined in table `creature_template`, can't load. ", entry);
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid model {1} defined in table `creature_template`, can't load.", entry, model.CreatureDisplayID);
|
||||
return false;
|
||||
}
|
||||
|
||||
SetDisplayId(displayID);
|
||||
SetNativeDisplayId(displayID);
|
||||
SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
|
||||
SetNativeDisplayId(model.CreatureDisplayID, model.DisplayScale);
|
||||
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
|
||||
|
||||
// Load creature equipment
|
||||
@@ -279,6 +283,8 @@ namespace Game.Entities
|
||||
|
||||
SetUInt32Value(ObjectFields.DynamicFlags, dynamicFlags);
|
||||
|
||||
SetUInt32Value(UnitFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
|
||||
|
||||
RemoveFlag(UnitFields.Flags, UnitFlags.InCombat);
|
||||
|
||||
SetBaseAttackTime(WeaponAttackType.BaseAttack, cInfo.BaseAttackTime);
|
||||
@@ -768,7 +774,8 @@ namespace Game.Entities
|
||||
if (!CreateFromProto(guidlow, entry, data, vehId))
|
||||
return false;
|
||||
|
||||
switch (GetCreatureTemplate().Rank)
|
||||
cinfo = GetCreatureTemplate(); // might be different than initially requested
|
||||
switch (cinfo.Rank)
|
||||
{
|
||||
case CreatureEliteType.Rare:
|
||||
m_corpseDelay = WorldConfig.GetUIntValue(WorldCfg.CorpseDecayRare);
|
||||
@@ -797,12 +804,12 @@ namespace Game.Entities
|
||||
Relocate(x, y, z, ang);
|
||||
}
|
||||
|
||||
uint displayID = GetNativeDisplayId();
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
|
||||
CreatureModel display = new CreatureModel(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f);
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref display, cinfo);
|
||||
if (minfo != null && !IsTotem()) // Cancel load if no model defined or if totem
|
||||
{
|
||||
SetDisplayId(displayID);
|
||||
SetNativeDisplayId(displayID);
|
||||
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
|
||||
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
|
||||
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
|
||||
}
|
||||
|
||||
@@ -815,10 +822,10 @@ namespace Game.Entities
|
||||
m_serverSideVisibilityDetect.SetValue(ServerSideVisibilityType.Ghost, GhostVisibilityType.Ghost);
|
||||
}
|
||||
|
||||
if (GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.IgnorePathfinding))
|
||||
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.IgnorePathfinding))
|
||||
AddUnitState(UnitState.IgnorePathfinding);
|
||||
|
||||
if (GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.ImmunityKnockback))
|
||||
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.ImmunityKnockback))
|
||||
{
|
||||
ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.KnockBack, true);
|
||||
ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.KnockBackDest, true);
|
||||
@@ -1014,9 +1021,9 @@ namespace Game.Entities
|
||||
CreatureTemplate cinfo = GetCreatureTemplate();
|
||||
if (cinfo != null)
|
||||
{
|
||||
if (displayId == cinfo.ModelId1 || displayId == cinfo.ModelId2 ||
|
||||
displayId == cinfo.ModelId3 || displayId == cinfo.ModelId4)
|
||||
displayId = 0;
|
||||
foreach (CreatureModel model in cinfo.Models)
|
||||
if (displayId != 0 && displayId == model.CreatureDisplayID)
|
||||
displayId = 0;
|
||||
|
||||
if (npcflag == (uint)cinfo.Npcflag)
|
||||
npcflag = 0;
|
||||
@@ -1620,12 +1627,12 @@ namespace Game.Entities
|
||||
|
||||
setDeathState(DeathState.JustRespawned);
|
||||
|
||||
uint displayID = GetNativeDisplayId();
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref displayID);
|
||||
CreatureModel display = new CreatureModel(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f);
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelRandomGender(ref display, GetCreatureTemplate());
|
||||
if (minfo != null) // Cancel load if no model defined
|
||||
{
|
||||
SetDisplayId(displayID);
|
||||
SetNativeDisplayId(displayID);
|
||||
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
|
||||
SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale);
|
||||
SetByteValue(UnitFields.Bytes0, 3, (byte)minfo.gender);
|
||||
}
|
||||
|
||||
@@ -2372,7 +2379,7 @@ namespace Game.Entities
|
||||
int targetLevelWithDelta = ((int)unitTarget.getLevel() + GetInt32Value(UnitFields.ScalingLevelDelta));
|
||||
|
||||
if (target.IsPlayer())
|
||||
targetLevelWithDelta += target.GetInt32Value(PlayerFields.ScalingLevelDelta);
|
||||
targetLevelWithDelta += target.GetInt32Value(ActivePlayerFields.ScalingPlayerLevelDelta);
|
||||
|
||||
return (uint)MathFunctions.RoundToInterval(ref targetLevelWithDelta, GetInt32Value(UnitFields.ScalingLevelMin), GetInt32Value(UnitFields.ScalingLevelMax));
|
||||
}
|
||||
@@ -2622,6 +2629,10 @@ namespace Game.Entities
|
||||
if (m_playerMovingMe != null)
|
||||
return;
|
||||
|
||||
// Creatures with CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE should control MovementFlags in your own scripts
|
||||
if (GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.NoMoveFlagsUpdate))
|
||||
return;
|
||||
|
||||
// Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
|
||||
float ground = GetMap().GetHeight(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZMinusOffset());
|
||||
|
||||
@@ -2653,23 +2664,30 @@ namespace Game.Entities
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(GetDisplayId());
|
||||
if (minfo != null)
|
||||
{
|
||||
SetFloatValue(UnitFields.BoundingRadius, minfo.BoundingRadius * scale);
|
||||
SetFloatValue(UnitFields.CombatReach, minfo.CombatReach * scale);
|
||||
SetFloatValue(UnitFields.BoundingRadius, (IsPet() ? 1.0f : minfo.BoundingRadius) * scale);
|
||||
SetFloatValue(UnitFields.CombatReach, (IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * scale);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetDisplayId(uint modelId)
|
||||
public override void SetDisplayId(uint modelId, float displayScale = 1f)
|
||||
{
|
||||
base.SetDisplayId(modelId);
|
||||
base.SetDisplayId(modelId, displayScale);
|
||||
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
|
||||
if (minfo != null)
|
||||
{
|
||||
SetFloatValue(UnitFields.BoundingRadius, minfo.BoundingRadius * GetObjectScale());
|
||||
SetFloatValue(UnitFields.CombatReach, minfo.CombatReach * GetObjectScale());
|
||||
SetFloatValue(UnitFields.BoundingRadius, (IsPet() ? 1.0f : minfo.BoundingRadius) * GetObjectScale());
|
||||
SetFloatValue(UnitFields.CombatReach, (IsPet() ? SharedConst.DefaultCombatReach : minfo.CombatReach) * GetObjectScale());
|
||||
}
|
||||
}
|
||||
|
||||
public void SetDisplayFromModel(int modelIdx)
|
||||
{
|
||||
CreatureModel model = GetCreatureTemplate().GetModelByIdx(modelIdx);
|
||||
if (model != null)
|
||||
SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
|
||||
}
|
||||
|
||||
public override void SetTarget(ObjectGuid guid)
|
||||
{
|
||||
if (IsFocusing(null, true))
|
||||
|
||||
@@ -28,10 +28,7 @@ namespace Game.Entities
|
||||
public uint Entry;
|
||||
public uint[] DifficultyEntry = new uint[SharedConst.MaxCreatureDifficulties];
|
||||
public uint[] KillCredit = new uint[SharedConst.MaxCreatureKillCredit];
|
||||
public uint ModelId1;
|
||||
public uint ModelId2;
|
||||
public uint ModelId3;
|
||||
public uint ModelId4;
|
||||
public List<CreatureModel> Models = new List<CreatureModel>();
|
||||
public string Name;
|
||||
public string FemaleName;
|
||||
public string SubName;
|
||||
@@ -91,75 +88,67 @@ namespace Game.Entities
|
||||
public CreatureFlagsExtra FlagsExtra;
|
||||
public uint ScriptID;
|
||||
|
||||
public uint GetRandomValidModelId()
|
||||
public CreatureModel GetModelByIdx(int idx)
|
||||
{
|
||||
byte c = 0;
|
||||
uint[] modelIDs = new uint[4];
|
||||
|
||||
if (ModelId1 != 0)
|
||||
modelIDs[c++] = ModelId1;
|
||||
if (ModelId2 != 0)
|
||||
modelIDs[c++] = ModelId2;
|
||||
if (ModelId3 != 0)
|
||||
modelIDs[c++] = ModelId3;
|
||||
if (ModelId4 != 0)
|
||||
modelIDs[c++] = ModelId4;
|
||||
|
||||
return c > 0 ? modelIDs[RandomHelper.IRand(0, c - 1)] : 0;
|
||||
}
|
||||
public uint GetFirstValidModelId()
|
||||
{
|
||||
if (ModelId1 != 0)
|
||||
return ModelId1;
|
||||
if (ModelId2 != 0)
|
||||
return ModelId2;
|
||||
if (ModelId3 != 0)
|
||||
return ModelId3;
|
||||
if (ModelId4 != 0)
|
||||
return ModelId4;
|
||||
return 0;
|
||||
return idx < Models.Count ? Models[idx] : null;
|
||||
}
|
||||
|
||||
public uint GetFirstInvisibleModel()
|
||||
public CreatureModel GetRandomValidModel()
|
||||
{
|
||||
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId1);
|
||||
if (modelInfo != null && modelInfo.IsTrigger)
|
||||
return ModelId1;
|
||||
if (Models.Empty())
|
||||
return null;
|
||||
|
||||
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId2);
|
||||
if (modelInfo != null && modelInfo.IsTrigger)
|
||||
return ModelId2;
|
||||
// If only one element, ignore the Probability (even if 0)
|
||||
if (Models.Count == 1)
|
||||
return Models[0];
|
||||
|
||||
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId3);
|
||||
if (modelInfo != null && modelInfo.IsTrigger)
|
||||
return ModelId3;
|
||||
var selectedItr = Models.SelectRandomElementByWeight(model =>
|
||||
{
|
||||
return model.Probability;
|
||||
});
|
||||
|
||||
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId4);
|
||||
if (modelInfo != null && modelInfo.IsTrigger)
|
||||
return ModelId4;
|
||||
return selectedItr;
|
||||
}
|
||||
public CreatureModel GetFirstValidModel()
|
||||
{
|
||||
foreach (CreatureModel model in Models)
|
||||
if (model.CreatureDisplayID != 0)
|
||||
return model;
|
||||
|
||||
return 11686;
|
||||
return null;
|
||||
}
|
||||
|
||||
public uint GetFirstVisibleModel()
|
||||
public CreatureModel GetModelWithDisplayId(uint displayId)
|
||||
{
|
||||
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId1);
|
||||
if (modelInfo != null && !modelInfo.IsTrigger)
|
||||
return ModelId1;
|
||||
foreach (CreatureModel model in Models)
|
||||
if (displayId == model.CreatureDisplayID)
|
||||
return model;
|
||||
|
||||
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId2);
|
||||
if (modelInfo != null && !modelInfo.IsTrigger)
|
||||
return ModelId2;
|
||||
return null;
|
||||
}
|
||||
|
||||
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId3);
|
||||
if (modelInfo != null && !modelInfo.IsTrigger)
|
||||
return ModelId3;
|
||||
public CreatureModel GetFirstInvisibleModel()
|
||||
{
|
||||
foreach (CreatureModel model in Models)
|
||||
{
|
||||
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(model.CreatureDisplayID);
|
||||
if (modelInfo != null && modelInfo.IsTrigger)
|
||||
return model;
|
||||
}
|
||||
|
||||
modelInfo = Global.ObjectMgr.GetCreatureModelInfo(ModelId4);
|
||||
if (modelInfo != null && !modelInfo.IsTrigger)
|
||||
return ModelId4;
|
||||
return CreatureModel.DefaultInvisibleModel;
|
||||
}
|
||||
|
||||
return 17519;
|
||||
public CreatureModel GetFirstVisibleModel()
|
||||
{
|
||||
foreach (CreatureModel model in Models)
|
||||
{
|
||||
CreatureModelInfo modelInfo = Global.ObjectMgr.GetCreatureModelInfo(model.CreatureDisplayID);
|
||||
if (modelInfo != null && !modelInfo.IsTrigger)
|
||||
return model;
|
||||
}
|
||||
|
||||
return CreatureModel.DefaultVisibleModel;
|
||||
}
|
||||
|
||||
public SkillType GetRequiredLootSkill()
|
||||
@@ -314,6 +303,24 @@ namespace Game.Entities
|
||||
public bool IsTrigger;
|
||||
}
|
||||
|
||||
public class CreatureModel
|
||||
{
|
||||
public static CreatureModel DefaultInvisibleModel = new CreatureModel(11686, 1.0f, 1.0f);
|
||||
public static CreatureModel DefaultVisibleModel = new CreatureModel(17519, 1.0f, 1.0f);
|
||||
|
||||
public uint CreatureDisplayID;
|
||||
public float DisplayScale;
|
||||
public float Probability;
|
||||
|
||||
public CreatureModel() { }
|
||||
public CreatureModel(uint creatureDisplayID, float displayScale, float probability)
|
||||
{
|
||||
CreatureDisplayID = creatureDisplayID;
|
||||
DisplayScale = displayScale;
|
||||
Probability = probability;
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatureAddon
|
||||
{
|
||||
public uint path_id;
|
||||
|
||||
@@ -316,6 +316,7 @@ namespace Game.Misc
|
||||
}
|
||||
|
||||
GossipPOI packet = new GossipPOI();
|
||||
packet.ID = pointOfInterest.ID;
|
||||
packet.Name = pointOfInterest.Name;
|
||||
|
||||
LocaleConstant locale = _session.GetSessionDbLocaleIndex();
|
||||
@@ -431,10 +432,11 @@ namespace Game.Misc
|
||||
packet.InformUnit = _session.GetPlayer().GetDivider();
|
||||
packet.QuestID = quest.Id;
|
||||
packet.PortraitGiver = quest.QuestGiverPortrait;
|
||||
packet.PortraitGiverMount = quest.QuestGiverPortraitMount;
|
||||
packet.PortraitTurnIn = quest.QuestTurnInPortrait;
|
||||
packet.AutoLaunched = autoLaunched;
|
||||
packet.DisplayPopup = displayPopup;
|
||||
packet.QuestFlags[0] = (uint)quest.Flags;
|
||||
packet.QuestFlags[0] = (uint)(quest.Flags & (WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) ? ~QuestFlags.AutoAccept : ~QuestFlags.None));
|
||||
packet.QuestFlags[1] = (uint)quest.FlagsEx;
|
||||
packet.SuggestedPartyMembers = quest.SuggestedPlayers;
|
||||
|
||||
@@ -501,6 +503,7 @@ namespace Game.Misc
|
||||
packet.Info.QuestID = quest.Id;
|
||||
packet.Info.QuestType = (int)quest.Type;
|
||||
packet.Info.QuestLevel = quest.Level;
|
||||
packet.Info.QuestScalingFactionGroup = quest.ScalingFactionGroup;
|
||||
packet.Info.QuestMaxScalingLevel = quest.MaxScalingLevel;
|
||||
packet.Info.QuestPackageID = quest.PackageID;
|
||||
packet.Info.QuestMinLevel = quest.MinLevel;
|
||||
@@ -532,12 +535,14 @@ namespace Game.Misc
|
||||
packet.Info.StartItem = quest.SourceItemId;
|
||||
packet.Info.Flags = (uint)quest.Flags;
|
||||
packet.Info.FlagsEx = (uint)quest.FlagsEx;
|
||||
packet.Info.FlagsEx2 = (uint)quest.FlagsEx2;
|
||||
packet.Info.RewardTitle = quest.RewardTitleId;
|
||||
packet.Info.RewardArenaPoints = quest.RewardArenaPoints;
|
||||
packet.Info.RewardSkillLineID = quest.RewardSkillId;
|
||||
packet.Info.RewardNumSkillUps = quest.RewardSkillPoints;
|
||||
packet.Info.RewardFactionFlags = quest.RewardReputationMask;
|
||||
packet.Info.PortraitGiver = quest.QuestGiverPortrait;
|
||||
packet.Info.PortraitGiverMount = quest.QuestGiverPortraitMount;
|
||||
packet.Info.PortraitTurnIn = quest.QuestTurnInPortrait;
|
||||
|
||||
for (byte i = 0; i < SharedConst.QuestItemDropCount; ++i)
|
||||
@@ -574,7 +579,7 @@ namespace Game.Misc
|
||||
packet.Info.POIPriority = quest.POIPriority;
|
||||
|
||||
packet.Info.AllowableRaces = quest.AllowableRaces;
|
||||
packet.Info.QuestRewardID = (int)quest.QuestRewardID;
|
||||
packet.Info.TreasurePickerID = (int)quest.TreasurePickerID;
|
||||
packet.Info.Expansion = quest.Expansion;
|
||||
|
||||
foreach (QuestObjective questObjective in quest.Objectives)
|
||||
@@ -654,6 +659,7 @@ namespace Game.Misc
|
||||
|
||||
packet.PortraitTurnIn = quest.QuestTurnInPortrait;
|
||||
packet.PortraitGiver = quest.QuestGiverPortrait;
|
||||
packet.PortraitGiverMount = quest.QuestGiverPortraitMount;
|
||||
packet.QuestPackageID = quest.PackageID;
|
||||
|
||||
packet.QuestData = offer;
|
||||
|
||||
@@ -15,8 +15,7 @@ namespace Game.Entities
|
||||
public Array<uint> ReqAbility = new Array<uint>(3);
|
||||
public byte ReqLevel;
|
||||
|
||||
public uint LearnedSpellId;
|
||||
public bool IsCastable() { return LearnedSpellId != SpellId; }
|
||||
public bool IsCastable() { return Global.SpellMgr.GetSpellInfo(SpellId).HasEffect(SpellEffectName.LearnSpell); }
|
||||
}
|
||||
|
||||
public class Trainer
|
||||
@@ -108,7 +107,7 @@ namespace Game.Entities
|
||||
|
||||
TrainerSpellState GetSpellState(Player player, TrainerSpell trainerSpell)
|
||||
{
|
||||
if (player.HasSpell(trainerSpell.IsCastable() ? trainerSpell.LearnedSpellId : trainerSpell.SpellId))
|
||||
if (player.HasSpell(trainerSpell.SpellId))
|
||||
return TrainerSpellState.Known;
|
||||
|
||||
// check race/class requirement
|
||||
@@ -128,10 +127,32 @@ namespace Game.Entities
|
||||
return TrainerSpellState.Unavailable;
|
||||
|
||||
// check ranks
|
||||
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(trainerSpell.LearnedSpellId);
|
||||
if (previousRankSpellId != 0)
|
||||
if (!player.HasSpell(previousRankSpellId))
|
||||
return TrainerSpellState.Unavailable;
|
||||
bool hasLearnSpellEffect = false;
|
||||
bool knowsAllLearnedSpells = true;
|
||||
foreach (SpellEffectInfo spellEffect in Global.SpellMgr.GetSpellInfo(trainerSpell.SpellId).GetEffectsForDifficulty(Difficulty.None))
|
||||
{
|
||||
if (spellEffect == null || !spellEffect.IsEffect(SpellEffectName.LearnSpell))
|
||||
continue;
|
||||
|
||||
hasLearnSpellEffect = true;
|
||||
if (!player.HasSpell(spellEffect.TriggerSpell))
|
||||
knowsAllLearnedSpells = false;
|
||||
|
||||
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(spellEffect.TriggerSpell);
|
||||
if (previousRankSpellId != 0)
|
||||
if (!player.HasSpell(previousRankSpellId))
|
||||
return TrainerSpellState.Unavailable;
|
||||
}
|
||||
|
||||
if (!hasLearnSpellEffect)
|
||||
{
|
||||
uint previousRankSpellId = Global.SpellMgr.GetPrevSpellInChain(trainerSpell.SpellId);
|
||||
if (previousRankSpellId != 0)
|
||||
if (!player.HasSpell(previousRankSpellId))
|
||||
return TrainerSpellState.Unavailable;
|
||||
}
|
||||
else if (knowsAllLearnedSpells)
|
||||
return TrainerSpellState.Known;
|
||||
|
||||
// check additional spell requirement
|
||||
foreach (var spellId in Global.SpellMgr.GetSpellsRequiredForSpellBounds(trainerSpell.SpellId))
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.DynamicObject;
|
||||
objectTypeId = TypeId.DynamicObject;
|
||||
|
||||
m_updateFlag = UpdateFlag.StationaryPosition;
|
||||
m_updateFlag.Stationary = true;
|
||||
|
||||
valuesCount = (int)DynamicObjectFields.End;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.GameObject;
|
||||
objectTypeId = TypeId.GameObject;
|
||||
|
||||
m_updateFlag = UpdateFlag.StationaryPosition | UpdateFlag.Rotation;
|
||||
m_updateFlag.Stationary = true;
|
||||
m_updateFlag.Rotation = true;
|
||||
|
||||
valuesCount = (int)GameObjectFields.End;
|
||||
m_respawnDelayTime = 300;
|
||||
@@ -219,7 +220,7 @@ namespace Game.Entities
|
||||
else
|
||||
{
|
||||
guid = ObjectGuid.Create(HighGuid.Transport, map.GenerateLowGuid(HighGuid.Transport));
|
||||
m_updateFlag |= UpdateFlag.Transport;
|
||||
m_updateFlag.ServerTime = true;
|
||||
}
|
||||
|
||||
_Create(guid);
|
||||
@@ -252,7 +253,7 @@ namespace Game.Entities
|
||||
|
||||
if (m_goTemplateAddon.WorldEffectID != 0)
|
||||
{
|
||||
m_updateFlag |= UpdateFlag.Gameobject;
|
||||
m_updateFlag.GameObject = true;
|
||||
SetWorldEffectID(m_goTemplateAddon.WorldEffectID);
|
||||
}
|
||||
}
|
||||
@@ -274,6 +275,8 @@ namespace Game.Entities
|
||||
SetGoState(goState);
|
||||
SetGoArtKit((byte)artKit);
|
||||
|
||||
SetUInt32Value(GameObjectFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
|
||||
|
||||
switch (goInfo.type)
|
||||
{
|
||||
case GameObjectTypes.FishingHole:
|
||||
@@ -356,7 +359,7 @@ namespace Game.Entities
|
||||
|
||||
if (gameObjectAddon != null && gameObjectAddon.WorldEffectID != 0)
|
||||
{
|
||||
m_updateFlag |= UpdateFlag.Gameobject;
|
||||
m_updateFlag.GameObject = true;
|
||||
SetWorldEffectID(gameObjectAddon.WorldEffectID);
|
||||
}
|
||||
|
||||
|
||||
@@ -194,6 +194,18 @@ namespace Game.Entities
|
||||
[FieldOffset(68)]
|
||||
public challengemodereward ChallengeModeReward;
|
||||
|
||||
[FieldOffset(68)]
|
||||
public multi Multi;
|
||||
|
||||
[FieldOffset(68)]
|
||||
public siegeableMulti SiegeableMulti;
|
||||
|
||||
[FieldOffset(68)]
|
||||
public siegeableMO SiegeableMO;
|
||||
|
||||
[FieldOffset(68)]
|
||||
public pvpReward PvpReward;
|
||||
|
||||
[FieldOffset(68)]
|
||||
public raw Raw;
|
||||
|
||||
@@ -264,6 +276,10 @@ namespace Game.Entities
|
||||
return CapturePoint.open;
|
||||
case GameObjectTypes.GatheringNode:
|
||||
return GatheringNode.open;
|
||||
case GameObjectTypes.ChallengeModeReward:
|
||||
return ChallengeModeReward.open;
|
||||
case GameObjectTypes.PvpReward:
|
||||
return PvpReward.open;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -490,7 +506,7 @@ namespace Game.Entities
|
||||
public uint usegrouplootrules; // 15 use group loot rules, enum { false, true, }; Default: false
|
||||
public uint floatingTooltip; // 16 floatingTooltip, enum { false, true, }; Default: false
|
||||
public uint conditionID1; // 17 conditionID1, References: PlayerCondition, NoValue = 0
|
||||
public int xpLevel; // 18 xpLevel, int, Min value: -1, Max value: 123, Default value: 0
|
||||
public uint xpLevel; // 18 XP Level Range, References: ContentTuning, NoValue = 0
|
||||
public uint xpDifficulty; // 19 xpDifficulty, enum { No Exp, Trivial, Very Small, Small, Substandard, Standard, High, Epic, Dungeon, 5, }; Default: No Exp
|
||||
public uint lootLevel; // 20 lootLevel, int, Min value: 0, Max value: 123, Default value: 0
|
||||
public uint GroupXP; // 21 Group XP, enum { false, true, }; Default: false
|
||||
@@ -505,6 +521,7 @@ namespace Game.Entities
|
||||
public uint chestPersonalLoot; // 30 chest Personal Loot, References: Treasure, NoValue = 0
|
||||
public uint turnpersonallootsecurityoff; // 31 turn personal loot security off, enum { false, true, }; Default: false
|
||||
public uint ChestProperties; // 32 Chest Properties, References: ChestProperties, NoValue = 0
|
||||
public uint chestPushLoot; // 33 chest Push Loot, References: Treasure, NoValue = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -710,6 +727,7 @@ namespace Game.Entities
|
||||
{
|
||||
public uint creatureID; // 0 creatureID, References: Creature, NoValue = 0
|
||||
public uint charges; // 1 charges, int, Min value: 0, Max value: 65535, Default value: 1
|
||||
public uint Preferonlyifinlineofsight; // 2 Prefer only if in line of sight (expensive), enum { false, true, }; Default: false
|
||||
}
|
||||
|
||||
|
||||
@@ -885,7 +903,10 @@ namespace Game.Entities
|
||||
public uint startOpen; // 1 startOpen, enum { false, true, }; Default: false
|
||||
public uint autoClose; // 2 autoClose (ms), int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
public uint BlocksPathsDown; // 3 Blocks Paths Down, enum { false, true, }; Default: false
|
||||
public uint PathBlockerBump; // 4 Path Blocker Bump (ft), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
|
||||
public int PathBlockerBump; // 4 Path Blocker Bump (ft), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
|
||||
public uint GiganticAOI; // 5 Gigantic AOI, enum { false, true, }; Default: false
|
||||
public uint InfiniteAOI; // 6 Infinite AOI, enum { false, true, }; Default: false
|
||||
public uint DoorisOpaque; // 7 Door is Opaque (Disable portal on close), enum { false, true, }; Default: false
|
||||
}
|
||||
|
||||
|
||||
@@ -971,7 +992,7 @@ namespace Game.Entities
|
||||
public struct phaseablemo
|
||||
{
|
||||
public int SpawnMap; // 0 Spawn Map, References: Map, NoValue = -1
|
||||
public uint AreaNameSet; // 1 Area Name Set (Index), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
|
||||
public int AreaNameSet; // 1 Area Name Set (Index), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
|
||||
public uint DoodadSetA; // 2 Doodad Set A, int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
public uint DoodadSetB; // 3 Doodad Set B, int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
}
|
||||
@@ -1009,7 +1030,7 @@ namespace Game.Entities
|
||||
|
||||
public struct uilink
|
||||
{
|
||||
public uint UILinkType; // 0 UI Link Type, enum { Adventure Journal, Obliterum Forge, }; Default: Adventure Journal
|
||||
public uint UILinkType; // 0 UI Link Type, enum { Adventure Journal, Obliterum Forge, Scrapping Machine}; Default: Adventure Journal
|
||||
public uint allowMounted; // 1 allowMounted, enum { false, true, }; Default: false
|
||||
public uint GiganticAOI; // 2 Gigantic AOI, enum { false, true, }; Default: false
|
||||
public uint spellFocusType; // 3 spellFocusType, References: SpellFocusObject, NoValue = 0
|
||||
@@ -1032,7 +1053,7 @@ namespace Game.Entities
|
||||
public uint openTextID; // 9 openTextID, References: BroadcastText, NoValue = 0
|
||||
public uint floatingTooltip; // 10 floatingTooltip, enum { false, true, }; Default: false
|
||||
public uint conditionID1; // 11 conditionID1, References: PlayerCondition, NoValue = 0
|
||||
public uint xpLevel; // 12 xpLevel, int, Min value: -1, Max value: 123, Default value: 0
|
||||
public uint XPLevelRange; // 12 XP Level Range, References: ContentTuning, NoValue = 0
|
||||
public uint xpDifficulty; // 13 xpDifficulty, enum { No Exp, Trivial, Very Small, Small, Substandard, Standard, High, Epic, Dungeon, 5, }; Default: No Exp
|
||||
public uint spell; // 14 spell, References: Spell, NoValue = 0
|
||||
public uint GiganticAOI; // 15 Gigantic AOI, enum { false, true, }; Default: false
|
||||
@@ -1041,12 +1062,44 @@ namespace Game.Entities
|
||||
public uint MaxNumberofLoots; // 18 Max Number of Loots, int, Min value: 1, Max value: 40, Default value: 10
|
||||
public uint logloot; // 19 log loot, enum { false, true, }; Default: false
|
||||
public uint linkedTrap; // 20 linkedTrap, References: GameObjects, NoValue = 0
|
||||
public uint PlayOpenAnimationonOpening; // 21 Play Open Animation on Opening, enum { false, true, }; Default: false
|
||||
}
|
||||
|
||||
public struct challengemodereward
|
||||
{
|
||||
public uint chestLoot; // 0 chestLoot, References: Treasure, NoValue = 0
|
||||
public uint WhenAvailable; // 1 When Available, References: GameObjectDisplayInfo, NoValue = 0
|
||||
public uint open; // 2 open, References: Lock_, NoValue = 0
|
||||
public uint openTextID; // 3 openTextID, References: BroadcastText, NoValue = 0
|
||||
}
|
||||
|
||||
public struct multi
|
||||
{
|
||||
public uint MultiProperties; // 0 Multi Properties, References: MultiProperties, NoValue = 0
|
||||
}
|
||||
|
||||
public struct siegeableMulti
|
||||
{
|
||||
public uint MultiProperties; // 0 Multi Properties, References: MultiProperties, NoValue = 0
|
||||
public uint InitialDamage; // 1 Initial Damage, enum { None, Raw, Ratio, }; Default: None
|
||||
}
|
||||
|
||||
public struct siegeableMO
|
||||
{
|
||||
public uint SiegeableProperties; // 0 Siegeable Properties, References: SiegeableProperties, NoValue = 0
|
||||
public uint DoodadSetA; // 1 Doodad Set A, int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
public uint DoodadSetB; // 2 Doodad Set B, int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
public uint DoodadSetC; // 3 Doodad Set C, int, Min value: 0, Max value: 2147483647, Default value: 0
|
||||
public int SpawnMap; // 4 Spawn Map, References: Map, NoValue = -1
|
||||
public int AreaNameSet; // 5 Area Name Set (Index), int, Min value: -2147483648, Max value: 2147483647, Default value: 0
|
||||
}
|
||||
|
||||
public struct pvpReward
|
||||
{
|
||||
public uint chestLoot; // 0 chestLoot, References: Treasure, NoValue = 0
|
||||
public uint WhenAvailable; // 1 When Available, References: GameObjectDisplayInfo, NoValue = 0
|
||||
public uint open; // 2 open, References: Lock_, NoValue = 0
|
||||
public uint openTextID; // 3 openTextID, References: BroadcastText, NoValue = 0
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.Item;
|
||||
objectTypeId = TypeId.Item;
|
||||
|
||||
m_updateFlag = UpdateFlag.None;
|
||||
valuesCount = (int)ItemFields.End;
|
||||
_dynamicValuesCount = (int)ItemDynamicFields.End;
|
||||
uState = ItemUpdateState.New;
|
||||
@@ -75,17 +74,6 @@ namespace Game.Entities
|
||||
{
|
||||
if (i < 5)
|
||||
SetSpellCharges(i, itemProto.Effects[i].Charges);
|
||||
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo((uint)itemProto.Effects[i].SpellID);
|
||||
if (spellInfo != null)
|
||||
{
|
||||
if (spellInfo.HasEffect(SpellEffectName.GiveArtifactPower))
|
||||
{
|
||||
uint artifactKnowledgeLevel = WorldConfig.GetUIntValue(WorldCfg.CurrencyStartArtifactKnowledge);
|
||||
if (artifactKnowledgeLevel != 0)
|
||||
SetModifier(ItemModifier.ArtifactKnowledgeLevel, artifactKnowledgeLevel + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetUInt32Value(ItemFields.Duration, itemProto.GetDuration());
|
||||
@@ -1484,7 +1472,7 @@ namespace Game.Entities
|
||||
Player owner = GetOwner();
|
||||
for (byte i = 0; i < ItemConst.MaxStats; ++i)
|
||||
{
|
||||
if ((owner ? GetItemStatValue(i, owner) : proto.GetItemStatValue(i)) != 0)
|
||||
if ((owner ? GetItemStatValue(i, owner) : proto.GetItemStatAllocation(i)) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1498,7 +1486,7 @@ namespace Game.Entities
|
||||
|
||||
for (byte i = 0; i < ItemConst.MaxStats; ++i)
|
||||
{
|
||||
if (bonus.ItemStatValue[i] != 0)
|
||||
if (bonus.ItemStatAllocation[i] != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1781,55 +1769,6 @@ namespace Game.Entities
|
||||
return proto.GetSellPrice();
|
||||
}
|
||||
|
||||
public int GetReforgableStat(ItemModType statType)
|
||||
{
|
||||
ItemTemplate proto = GetTemplate();
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
if ((ItemModType)proto.GetItemStatType(i) == statType)
|
||||
return proto.GetItemStatValue(i);
|
||||
|
||||
int randomPropId = GetItemRandomPropertyId();
|
||||
if (randomPropId == 0)
|
||||
return 0;
|
||||
|
||||
if (randomPropId < 0)
|
||||
{
|
||||
ItemRandomSuffixRecord randomSuffix = CliDB.ItemRandomSuffixStorage.LookupByKey(-randomPropId);
|
||||
if (randomSuffix == null)
|
||||
return 0;
|
||||
|
||||
for (var e = EnchantmentSlot.Prop0; e <= EnchantmentSlot.Prop4; ++e)
|
||||
{
|
||||
var enchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(e));
|
||||
if (enchant != null)
|
||||
for (uint f = 0; f < ItemConst.MaxItemEnchantmentEffects; ++f)
|
||||
if (enchant.Effect[f] == ItemEnchantmentType.Stat && (ItemModType)enchant.EffectArg[f] == statType)
|
||||
for (int k = 0; k < 5; ++k)
|
||||
if (randomSuffix.Enchantment[k] == enchant.Id)
|
||||
return (int)((randomSuffix.AllocationPct[k] * GetItemSuffixFactor()) / 10000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var randomProp = CliDB.ItemRandomPropertiesStorage.LookupByKey(randomPropId);
|
||||
if (randomProp == null)
|
||||
return 0;
|
||||
|
||||
for (var e = EnchantmentSlot.Prop0; e <= EnchantmentSlot.Prop4; ++e)
|
||||
{
|
||||
var enchant = CliDB.SpellItemEnchantmentStorage.LookupByKey(GetEnchantmentId(e));
|
||||
if (enchant != null)
|
||||
for (uint f = 0; f < ItemConst.MaxItemEnchantmentEffects; ++f)
|
||||
if (enchant.Effect[f] == ItemEnchantmentType.Stat && (ItemModType)enchant.EffectArg[f] == statType)
|
||||
for (int k = 0; k < ItemConst.MaxItemRandomProperties; ++k)
|
||||
if (randomProp.Enchantment[k] == enchant.Id)
|
||||
return (int)(enchant.EffectPointsMin[k]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void ItemContainerSaveLootToDB()
|
||||
{
|
||||
// Saves the money and item loot associated with an openable item to the DB
|
||||
@@ -2038,12 +1977,12 @@ namespace Game.Entities
|
||||
if (fixedLevel != 0)
|
||||
level = fixedLevel;
|
||||
else
|
||||
level = Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
|
||||
level = (uint)Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
|
||||
|
||||
SandboxScalingRecord sandbox = CliDB.SandboxScalingStorage.LookupByKey(bonusData.SandboxScalingId);
|
||||
if (sandbox != null)
|
||||
if ((Convert.ToBoolean(sandbox.Flags & 2) || sandbox.MinLevel != 0 || sandbox.MaxLevel != 0) && !Convert.ToBoolean(sandbox.Flags & 4))
|
||||
level = Math.Min(Math.Max(level, sandbox.MinLevel), sandbox.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)
|
||||
@@ -2090,7 +2029,7 @@ namespace Game.Entities
|
||||
return (int)(Math.Floor(statValue + 0.5f));
|
||||
}
|
||||
|
||||
return _bonusData.ItemStatValue[index];
|
||||
return 0;
|
||||
}
|
||||
|
||||
public ItemDisenchantLootRecord GetDisenchantLoot(Player owner)
|
||||
@@ -2114,7 +2053,7 @@ namespace Game.Entities
|
||||
byte expansion = itemTemplate.GetRequiredExpansion();
|
||||
foreach (ItemDisenchantLootRecord disenchant in CliDB.ItemDisenchantLootStorage.Values)
|
||||
{
|
||||
if (disenchant.ClassID != itemClass)
|
||||
if (disenchant.Class != itemClass)
|
||||
continue;
|
||||
|
||||
if (disenchant.Subclass >= 0 && itemSubClass != 0)
|
||||
@@ -2404,8 +2343,6 @@ namespace Game.Entities
|
||||
uint artifactKnowledgeLevel = 1;
|
||||
if (sourceItem != null && sourceItem.GetModifier(ItemModifier.ArtifactKnowledgeLevel) != 0)
|
||||
artifactKnowledgeLevel = sourceItem.GetModifier(ItemModifier.ArtifactKnowledgeLevel);
|
||||
else if (artifactCategoryId == ArtifactCategory.Primary)
|
||||
artifactKnowledgeLevel = WorldConfig.GetUIntValue(WorldCfg.CurrencyStartArtifactKnowledge) + 1;
|
||||
|
||||
GtArtifactKnowledgeMultiplierRecord artifactKnowledge = CliDB.ArtifactKnowledgeMultiplierGameTable.GetRow(artifactKnowledgeLevel);
|
||||
if (artifactKnowledge != null)
|
||||
@@ -2437,12 +2374,12 @@ namespace Game.Entities
|
||||
ScalingStatDistributionRecord ssd = CliDB.ScalingStatDistributionStorage.LookupByKey(_bonusData.ScalingStatDistribution);
|
||||
if (ssd != null)
|
||||
{
|
||||
level = Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
|
||||
level = (uint)Math.Min(Math.Max(level, ssd.MinLevel), ssd.MaxLevel);
|
||||
|
||||
SandboxScalingRecord sandbox = CliDB.SandboxScalingStorage.LookupByKey(_bonusData.SandboxScalingId);
|
||||
if (sandbox != null)
|
||||
if ((sandbox.Flags.HasAnyFlag(2u) || sandbox.MinLevel != 0 || sandbox.MaxLevel != 0) && !sandbox.Flags.HasAnyFlag(4u))
|
||||
level = Math.Min(Math.Max(level, sandbox.MinLevel), sandbox.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);
|
||||
|
||||
SetModifier(ItemModifier.ScalingStatDistributionFixedLevel, level);
|
||||
}
|
||||
@@ -2838,9 +2775,6 @@ namespace Game.Entities
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
ItemStatType[i] = proto.GetItemStatType(i);
|
||||
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
ItemStatValue[i] = proto.GetItemStatValue(i);
|
||||
|
||||
for (uint i = 0; i < ItemConst.MaxStats; ++i)
|
||||
ItemStatAllocation[i] = proto.GetItemStatAllocation(i);
|
||||
|
||||
@@ -2948,7 +2882,7 @@ namespace Game.Entities
|
||||
if (values[1] < _state.ScalingStatDistributionPriority)
|
||||
{
|
||||
ScalingStatDistribution = (uint)values[0];
|
||||
SandboxScalingId = (uint)values[2];
|
||||
ContentTuningId = (uint)values[2];
|
||||
_state.ScalingStatDistributionPriority = values[1];
|
||||
HasFixedLevel = type == ItemBonusType.ScalingStatDistributionFixed;
|
||||
}
|
||||
@@ -2969,7 +2903,6 @@ namespace Game.Entities
|
||||
public int ItemLevelBonus;
|
||||
public int RequiredLevel;
|
||||
public int[] ItemStatType = new int[ItemConst.MaxStats];
|
||||
public int[] ItemStatValue = new int[ItemConst.MaxStats];
|
||||
public int[] ItemStatAllocation = new int[ItemConst.MaxStats];
|
||||
public float[] ItemStatSocketCostMultiplier = new float[ItemConst.MaxStats];
|
||||
public SocketColor[] socketColor = new SocketColor[ItemConst.MaxGemSockets];
|
||||
@@ -2977,7 +2910,7 @@ namespace Game.Entities
|
||||
public uint AppearanceModID;
|
||||
public float RepairCostMultiplier;
|
||||
public uint ScalingStatDistribution;
|
||||
public uint SandboxScalingId;
|
||||
public uint ContentTuningId;
|
||||
public uint DisenchantLootId;
|
||||
public uint[] GemItemLevelBonus = new uint[ItemConst.MaxGemSockets];
|
||||
public int[] GemRelicType = new int[ItemConst.MaxGemSockets];
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace Game.Entities
|
||||
if (GetFlags().HasAnyFlag(ItemFlags.IsBoundToAccount) && alwaysAllowBoundToAccount)
|
||||
return true;
|
||||
|
||||
uint spec = player.GetUInt32Value(PlayerFields.LootSpecId);
|
||||
uint spec = player.GetUInt32Value(ActivePlayerFields.LootSpecId);
|
||||
if (spec == 0)
|
||||
spec = player.GetUInt32Value(PlayerFields.CurrentSpecId);
|
||||
if (spec == 0)
|
||||
@@ -277,11 +277,6 @@ namespace Game.Entities
|
||||
Cypher.Assert(index < ItemConst.MaxStats);
|
||||
return ExtendedData.StatModifierBonusStat[index];
|
||||
}
|
||||
public int GetItemStatValue(uint index)
|
||||
{
|
||||
Cypher.Assert(index < ItemConst.MaxStats);
|
||||
return ExtendedData.ItemStatValue[index];
|
||||
}
|
||||
public int GetItemStatAllocation(uint index)
|
||||
{
|
||||
Cypher.Assert(index < ItemConst.MaxStats);
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Game.Entities
|
||||
_fieldNotifyFlags = UpdateFieldFlags.Dynamic;
|
||||
|
||||
m_movementInfo = new MovementInfo();
|
||||
m_updateFlag = UpdateFlag.None;
|
||||
m_updateFlag.Clear();
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
@@ -110,7 +110,6 @@ namespace Game.Entities
|
||||
InitValues();
|
||||
|
||||
SetGuidValue(ObjectFields.Guid, guid);
|
||||
SetUInt16Value(ObjectFields.Type, 0, (ushort)objectTypeMask);
|
||||
}
|
||||
|
||||
public string _ConcatFields(object startIndex, uint size)
|
||||
@@ -148,10 +147,17 @@ namespace Game.Entities
|
||||
return;
|
||||
|
||||
UpdateType updateType = UpdateType.CreateObject;
|
||||
UpdateFlag flags = m_updateFlag;
|
||||
TypeId tempObjectType = objectTypeId;
|
||||
TypeMask tempObjectTypeMask = objectTypeMask;
|
||||
CreateObjectBits flags = m_updateFlag;
|
||||
|
||||
if (target == this)
|
||||
flags |= UpdateFlag.Self;
|
||||
{
|
||||
flags.ThisIsYou = true;
|
||||
flags.ActivePlayer = true;
|
||||
tempObjectType = TypeId.Player;
|
||||
tempObjectTypeMask |= TypeMask.Player;
|
||||
}
|
||||
|
||||
switch (GetGUID().GetHigh())
|
||||
{
|
||||
@@ -176,16 +182,13 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
|
||||
if (!flags.HasAnyFlag(UpdateFlag.Living))
|
||||
{
|
||||
if (!m_movementInfo.transport.guid.IsEmpty())
|
||||
flags |= UpdateFlag.TransportPosition;
|
||||
if (!flags.MovementUpdate && !m_movementInfo.transport.guid.IsEmpty())
|
||||
flags.MovementTransport = true;
|
||||
|
||||
if (GetAIAnimKitId() != 0 || GetMovementAnimKitId() != 0 || GetMeleeAnimKitId() != 0)
|
||||
flags |= UpdateFlag.AnimKits;
|
||||
}
|
||||
if (GetAIAnimKitId() != 0 || GetMovementAnimKitId() != 0 || GetMeleeAnimKitId() != 0)
|
||||
flags.AnimKit = true;
|
||||
|
||||
if (flags.HasAnyFlag(UpdateFlag.StationaryPosition))
|
||||
if (flags.Stationary)
|
||||
{
|
||||
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
|
||||
if (isTypeMask(TypeMask.GameObject))
|
||||
@@ -206,12 +209,13 @@ namespace Game.Entities
|
||||
Unit unit = ToUnit();
|
||||
if (unit)
|
||||
if (unit.GetVictim())
|
||||
flags |= UpdateFlag.HasTarget;
|
||||
flags.CombatVictim = true;
|
||||
|
||||
WorldPacket buffer = new WorldPacket();
|
||||
buffer.WriteUInt8(updateType);
|
||||
buffer.WritePackedGuid(GetGUID());
|
||||
buffer.WriteUInt8(objectTypeId);
|
||||
buffer.WriteUInt8(tempObjectType);
|
||||
buffer.WriteUInt32(tempObjectTypeMask);
|
||||
|
||||
BuildMovementUpdate(buffer, flags);
|
||||
BuildValuesUpdate(updateType, buffer, target);
|
||||
@@ -305,25 +309,8 @@ namespace Game.Entities
|
||||
return new ObjectGuid(GetUInt64Value((int)index + 2), GetUInt64Value(index));
|
||||
}
|
||||
|
||||
public void BuildMovementUpdate(WorldPacket data, UpdateFlag flags)
|
||||
public void BuildMovementUpdate(WorldPacket data, CreateObjectBits flags)
|
||||
{
|
||||
bool NoBirthAnim = false;
|
||||
bool EnablePortals = false;
|
||||
bool PlayHoverAnim = false;
|
||||
bool HasMovementUpdate = flags.HasAnyFlag(UpdateFlag.Living);
|
||||
bool HasMovementTransport = flags.HasAnyFlag(UpdateFlag.TransportPosition);
|
||||
bool Stationary = flags.HasAnyFlag(UpdateFlag.StationaryPosition);
|
||||
bool CombatVictim = flags.HasAnyFlag(UpdateFlag.HasTarget);
|
||||
bool ServerTime = flags.HasAnyFlag(UpdateFlag.Transport);
|
||||
bool VehicleCreate = flags.HasAnyFlag(UpdateFlag.Vehicle);
|
||||
bool AnimKitCreate = flags.HasAnyFlag(UpdateFlag.AnimKits);
|
||||
bool Rotation = flags.HasAnyFlag(UpdateFlag.Rotation);
|
||||
bool HasAreaTrigger = flags.HasAnyFlag(UpdateFlag.Areatrigger);
|
||||
bool HasGameObject = flags.HasAnyFlag(UpdateFlag.Gameobject);
|
||||
bool ThisIsYou = flags.HasAnyFlag(UpdateFlag.Self);
|
||||
bool SmoothPhasing = false;
|
||||
bool SceneObjCreate = false;
|
||||
bool PlayerCreateData = GetTypeId() == TypeId.Player && ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max;
|
||||
int PauseTimesCount = 0;
|
||||
|
||||
GameObject go = ToGameObject();
|
||||
@@ -333,26 +320,27 @@ namespace Game.Entities
|
||||
PauseTimesCount = go.m_goValue.Transport.StopFrames.Count;
|
||||
}
|
||||
|
||||
data.WriteBit(NoBirthAnim);
|
||||
data.WriteBit(EnablePortals);
|
||||
data.WriteBit(PlayHoverAnim);
|
||||
data.WriteBit(HasMovementUpdate);
|
||||
data.WriteBit(HasMovementTransport);
|
||||
data.WriteBit(Stationary);
|
||||
data.WriteBit(CombatVictim);
|
||||
data.WriteBit(ServerTime);
|
||||
data.WriteBit(VehicleCreate);
|
||||
data.WriteBit(AnimKitCreate);
|
||||
data.WriteBit(Rotation);
|
||||
data.WriteBit(HasAreaTrigger);
|
||||
data.WriteBit(HasGameObject);
|
||||
data.WriteBit(SmoothPhasing);
|
||||
data.WriteBit(ThisIsYou);
|
||||
data.WriteBit(SceneObjCreate);
|
||||
data.WriteBit(PlayerCreateData);
|
||||
data.WriteBit(flags.NoBirthAnim);
|
||||
data.WriteBit(flags.EnablePortals);
|
||||
data.WriteBit(flags.PlayHoverAnim);
|
||||
data.WriteBit(flags.MovementUpdate);
|
||||
data.WriteBit(flags.MovementTransport);
|
||||
data.WriteBit(flags.Stationary);
|
||||
data.WriteBit(flags.CombatVictim);
|
||||
data.WriteBit(flags.ServerTime);
|
||||
data.WriteBit(flags.Vehicle);
|
||||
data.WriteBit(flags.AnimKit);
|
||||
data.WriteBit(flags.Rotation);
|
||||
data.WriteBit(flags.AreaTrigger);
|
||||
data.WriteBit(flags.GameObject);
|
||||
data.WriteBit(flags.SmoothPhasing);
|
||||
data.WriteBit(flags.ThisIsYou);
|
||||
data.WriteBit(flags.SceneObject);
|
||||
data.WriteBit(flags.ActivePlayer);
|
||||
data.WriteBit(flags.Conversation);
|
||||
data.FlushBits();
|
||||
|
||||
if (HasMovementUpdate)
|
||||
if (flags.MovementUpdate)
|
||||
{
|
||||
Unit unit = ToUnit();
|
||||
bool HasFallDirection = unit.HasUnitMovementFlag(MovementFlag.Falling);
|
||||
@@ -432,7 +420,7 @@ namespace Game.Entities
|
||||
|
||||
data.WriteUInt32(PauseTimesCount);
|
||||
|
||||
if (Stationary)
|
||||
if (flags.Stationary)
|
||||
{
|
||||
WorldObject self = this;
|
||||
data.WriteFloat(self.GetStationaryX());
|
||||
@@ -441,10 +429,10 @@ namespace Game.Entities
|
||||
data.WriteFloat(self.GetStationaryO());
|
||||
}
|
||||
|
||||
if (CombatVictim)
|
||||
if (flags.CombatVictim)
|
||||
data.WritePackedGuid(ToUnit().GetVictim().GetGUID()); // CombatVictim
|
||||
|
||||
if (ServerTime)
|
||||
if (flags.ServerTime)
|
||||
{
|
||||
GameObject go1 = ToGameObject();
|
||||
/** @TODO Use IsTransport() to also handle type 11 (TRANSPORT)
|
||||
@@ -458,21 +446,21 @@ namespace Game.Entities
|
||||
data.WriteUInt32(Time.GetMSTime());
|
||||
}
|
||||
|
||||
if (VehicleCreate)
|
||||
if (flags.Vehicle)
|
||||
{
|
||||
Unit unit = ToUnit();
|
||||
data.WriteUInt32(unit.GetVehicleKit().GetVehicleInfo().Id); // RecID
|
||||
data.WriteFloat(unit.GetOrientation()); // InitialRawFacing
|
||||
}
|
||||
|
||||
if (AnimKitCreate)
|
||||
if (flags.AnimKit)
|
||||
{
|
||||
data.WriteUInt16(GetAIAnimKitId()); // AiID
|
||||
data.WriteUInt16(GetMovementAnimKitId()); // MovementID
|
||||
data.WriteUInt16(GetMeleeAnimKitId()); // MeleeID
|
||||
}
|
||||
|
||||
if (Rotation)
|
||||
if (flags.Rotation)
|
||||
data.WriteInt64(ToGameObject().GetPackedWorldRotation()); // Rotation
|
||||
|
||||
if (go)
|
||||
@@ -481,13 +469,13 @@ namespace Game.Entities
|
||||
data.WriteUInt32(go.m_goValue.Transport.StopFrames[i]);
|
||||
}
|
||||
|
||||
if (HasMovementTransport)
|
||||
if (flags.MovementTransport)
|
||||
{
|
||||
WorldObject self = this;
|
||||
MovementExtensions.WriteTransportInfo(data, self.m_movementInfo.transport);
|
||||
}
|
||||
|
||||
if (HasAreaTrigger)
|
||||
if (flags.AreaTrigger)
|
||||
{
|
||||
AreaTrigger areaTrigger = ToAreaTrigger();
|
||||
AreaTriggerMiscTemplate areaTriggerMiscTemplate = areaTrigger.GetMiscTemplate();
|
||||
@@ -508,9 +496,10 @@ namespace Game.Entities
|
||||
bool hasMorphCurveID = areaTriggerMiscTemplate.MorphCurveId != 0;
|
||||
bool hasFacingCurveID = areaTriggerMiscTemplate.FacingCurveId != 0;
|
||||
bool hasMoveCurveID = areaTriggerMiscTemplate.MoveCurveId != 0;
|
||||
bool hasUnk2 = areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk2);
|
||||
bool hasAnimation = areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasAnimID);
|
||||
bool hasUnk3 = areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk3);
|
||||
bool hasUnk4 = areaTriggerTemplate.HasFlag(AreaTriggerFlags.Unk4);
|
||||
bool hasAnimKitID = areaTriggerTemplate.HasFlag(AreaTriggerFlags.HasAnimKitID);
|
||||
bool hasAnimProgress = false;
|
||||
bool hasAreaTriggerSphere = areaTriggerTemplate.IsSphere();
|
||||
bool hasAreaTriggerBox = areaTriggerTemplate.IsBox();
|
||||
bool hasAreaTriggerPolygon = areaTriggerTemplate.IsPolygon();
|
||||
@@ -529,9 +518,10 @@ namespace Game.Entities
|
||||
data.WriteBit(hasMorphCurveID);
|
||||
data.WriteBit(hasFacingCurveID);
|
||||
data.WriteBit(hasMoveCurveID);
|
||||
data.WriteBit(hasUnk2);
|
||||
data.WriteBit(hasAnimation);
|
||||
data.WriteBit(hasAnimKitID);
|
||||
data.WriteBit(hasUnk3);
|
||||
data.WriteBit(hasUnk4);
|
||||
data.WriteBit(hasAnimProgress);
|
||||
data.WriteBit(hasAreaTriggerSphere);
|
||||
data.WriteBit(hasAreaTriggerBox);
|
||||
data.WriteBit(hasAreaTriggerPolygon);
|
||||
@@ -567,10 +557,13 @@ namespace Game.Entities
|
||||
if (hasMoveCurveID)
|
||||
data.WriteUInt32(areaTriggerMiscTemplate.MoveCurveId);
|
||||
|
||||
if (hasUnk2)
|
||||
data.WriteInt32(0);
|
||||
if (hasAnimation)
|
||||
data.WriteInt32(areaTriggerMiscTemplate.AnimId);
|
||||
|
||||
if (hasUnk4)
|
||||
if (hasAnimKitID)
|
||||
data.WriteUInt32(areaTriggerMiscTemplate.AnimKitId);
|
||||
|
||||
if (hasAnimProgress)
|
||||
data.WriteUInt32(0);
|
||||
|
||||
if (hasAreaTriggerSphere)
|
||||
@@ -627,7 +620,7 @@ namespace Game.Entities
|
||||
areaTrigger.GetCircularMovementInfo().Value.Write(data);
|
||||
}
|
||||
|
||||
if (HasGameObject)
|
||||
if (flags.GameObject)
|
||||
{
|
||||
bool bit8 = false;
|
||||
uint Int1 = 0;
|
||||
@@ -642,7 +635,7 @@ namespace Game.Entities
|
||||
data.WriteUInt32(Int1);
|
||||
}
|
||||
|
||||
//if (SmoothPhasing)
|
||||
//if (flags.SmoothPhasing)
|
||||
//{
|
||||
// data.WriteBit(ReplaceActive);
|
||||
// data.WriteBit(HasReplaceObjectt);
|
||||
@@ -651,7 +644,7 @@ namespace Game.Entities
|
||||
// *data << ObjectGuid(ReplaceObject);
|
||||
//}
|
||||
|
||||
//if (SceneObjCreate)
|
||||
//if (flags.SceneObject)
|
||||
//{
|
||||
// data.WriteBit(HasLocalScriptData);
|
||||
// data.WriteBit(HasPetBattleFullUpdate);
|
||||
@@ -761,7 +754,7 @@ namespace Game.Entities
|
||||
// }
|
||||
//}
|
||||
|
||||
if (PlayerCreateData)
|
||||
if (flags.ActivePlayer)
|
||||
{
|
||||
bool HasSceneInstanceIDs = false;
|
||||
bool HasRuneState = ToUnit().GetPowerIndex(PowerType.Runes) != (int)PowerType.Max;
|
||||
@@ -788,6 +781,14 @@ namespace Game.Entities
|
||||
data.WriteUInt8((baseCd - (float)player.GetRuneCooldown(i)) / baseCd * 255);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags.Conversation)
|
||||
{
|
||||
Conversation self = ToConversation();
|
||||
if (data.WriteBit(self.GetTextureKitId() != 0))
|
||||
data.WriteUInt32(self.GetTextureKitId());
|
||||
data.FlushBits();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void BuildValuesUpdate(UpdateType updatetype, ByteBuffer data, Player target)
|
||||
@@ -819,13 +820,17 @@ namespace Game.Entities
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
uint valueCount = _dynamicValuesCount;
|
||||
if (target != this && GetTypeId() == TypeId.Player)
|
||||
valueCount = (uint)PlayerDynamicFields.End;
|
||||
|
||||
ByteBuffer fieldBuffer = new ByteBuffer();
|
||||
UpdateMask fieldMask = new UpdateMask(_dynamicValuesCount);
|
||||
UpdateMask fieldMask = new UpdateMask(valueCount);
|
||||
|
||||
uint[] flags;
|
||||
uint visibleFlag = GetDynamicUpdateFieldData(target, out flags);
|
||||
|
||||
for (var index = 0; index < _dynamicValuesCount; ++index)
|
||||
for (var index = 0; index < valueCount; ++index)
|
||||
{
|
||||
ByteBuffer valueBuffer = new ByteBuffer();
|
||||
var values = _dynamicValues[index];
|
||||
@@ -909,7 +914,17 @@ namespace Game.Entities
|
||||
{
|
||||
case TypeId.Item:
|
||||
case TypeId.Container:
|
||||
flags = UpdateFieldFlags.ItemUpdateFieldFlags;
|
||||
flags = UpdateFieldFlags.ContainerUpdateFieldFlags;
|
||||
if (((Item)this).GetOwnerGUID() == target.GetGUID())
|
||||
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
|
||||
break;
|
||||
case TypeId.AzeriteEmpoweredItem:
|
||||
flags = UpdateFieldFlags.AzeriteEmpoweredItemUpdateFieldFlags;
|
||||
if (((Item)this).GetOwnerGUID() == target.GetGUID())
|
||||
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
|
||||
break;
|
||||
case TypeId.AzeriteItem:
|
||||
flags = UpdateFieldFlags.AzeriteItemUpdateFieldFlags;
|
||||
if (((Item)this).GetOwnerGUID() == target.GetGUID())
|
||||
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
|
||||
break;
|
||||
@@ -954,6 +969,7 @@ namespace Game.Entities
|
||||
flags = UpdateFieldFlags.ConversationUpdateFieldFlags;
|
||||
break;
|
||||
case TypeId.Object:
|
||||
case TypeId.ActivePlayer:
|
||||
Cypher.Assert(false);
|
||||
break;
|
||||
}
|
||||
@@ -971,6 +987,8 @@ namespace Game.Entities
|
||||
{
|
||||
case TypeId.Item:
|
||||
case TypeId.Container:
|
||||
case TypeId.AzeriteEmpoweredItem:
|
||||
case TypeId.AzeriteItem:
|
||||
flags = UpdateFieldFlags.ItemDynamicUpdateFieldFlags;
|
||||
if (((Item)this).GetOwnerGUID() == target.GetGUID())
|
||||
visibleFlag |= UpdateFieldFlags.Owner | UpdateFieldFlags.ItemOwner;
|
||||
@@ -1660,6 +1678,16 @@ namespace Game.Entities
|
||||
corpseVisibility = true;
|
||||
}
|
||||
}
|
||||
|
||||
Unit target = obj.ToUnit();
|
||||
if (target)
|
||||
{
|
||||
// Don't allow to detect vehicle accessories if you can't see vehicle
|
||||
Unit vehicle = target.GetVehicleBase();
|
||||
if (vehicle)
|
||||
if (!thisPlayer.HaveAtClient(vehicle))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WorldObject viewpoint = this;
|
||||
@@ -1802,7 +1830,7 @@ namespace Game.Entities
|
||||
if (!HasInArc(MathFunctions.PI, obj))
|
||||
return false;
|
||||
|
||||
GameObject go = ToGameObject();
|
||||
GameObject go = obj.ToGameObject();
|
||||
for (int i = 0; i < (int)StealthType.Max; ++i)
|
||||
{
|
||||
if (!Convert.ToBoolean(obj.m_stealth.GetFlags() & (1 << i)))
|
||||
@@ -1896,6 +1924,9 @@ namespace Game.Entities
|
||||
|
||||
public virtual void ResetMap()
|
||||
{
|
||||
if (_currMap == null)
|
||||
return;
|
||||
|
||||
Cypher.Assert(_currMap != null);
|
||||
Cypher.Assert(!IsInWorld);
|
||||
if (IsWorldObject())
|
||||
@@ -2337,7 +2368,7 @@ namespace Game.Entities
|
||||
return distsq < maxdist * maxdist;
|
||||
}
|
||||
|
||||
public bool IsWithinLOSInMap(WorldObject obj)
|
||||
public bool IsWithinLOSInMap(WorldObject obj, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing)
|
||||
{
|
||||
if (!IsInMap(obj))
|
||||
return false;
|
||||
@@ -2348,7 +2379,7 @@ namespace Game.Entities
|
||||
else
|
||||
obj.GetHitSpherePointFor(GetPosition(), out x, out y, out z);
|
||||
|
||||
return IsWithinLOS(x, y, z);
|
||||
return IsWithinLOS(x, y, z, ignoreFlags);
|
||||
}
|
||||
|
||||
public float GetDistance(WorldObject obj)
|
||||
@@ -2426,7 +2457,7 @@ namespace Game.Entities
|
||||
return obj && IsInMap(obj) && IsInPhase(obj) && _IsWithinDist(obj, dist2compare, is3D);
|
||||
}
|
||||
|
||||
public bool IsWithinLOS(float ox, float oy, float oz)
|
||||
public bool IsWithinLOS(float ox, float oy, float oz, ModelIgnoreFlags ignoreFlags = ModelIgnoreFlags.Nothing)
|
||||
{
|
||||
if (IsInWorld)
|
||||
{
|
||||
@@ -2436,7 +2467,7 @@ namespace Game.Entities
|
||||
else
|
||||
GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z);
|
||||
|
||||
return GetMap().isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f);
|
||||
return GetMap().isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, ignoreFlags);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2853,7 +2884,7 @@ namespace Game.Entities
|
||||
#region Fields
|
||||
public TypeMask objectTypeMask { get; set; }
|
||||
protected TypeId objectTypeId { get; set; }
|
||||
protected UpdateFlag m_updateFlag { get; set; }
|
||||
protected CreateObjectBits m_updateFlag;
|
||||
|
||||
protected UpdateValues[] updateValues;
|
||||
protected uint[][] _dynamicValues;
|
||||
@@ -2997,4 +3028,48 @@ namespace Game.Entities
|
||||
public float xyspeed;
|
||||
}
|
||||
}
|
||||
|
||||
public struct CreateObjectBits
|
||||
{
|
||||
public bool NoBirthAnim;
|
||||
public bool EnablePortals;
|
||||
public bool PlayHoverAnim;
|
||||
public bool MovementUpdate;
|
||||
public bool MovementTransport;
|
||||
public bool Stationary;
|
||||
public bool CombatVictim;
|
||||
public bool ServerTime;
|
||||
public bool Vehicle;
|
||||
public bool AnimKit;
|
||||
public bool Rotation;
|
||||
public bool AreaTrigger;
|
||||
public bool GameObject;
|
||||
public bool SmoothPhasing;
|
||||
public bool ThisIsYou;
|
||||
public bool SceneObject;
|
||||
public bool ActivePlayer;
|
||||
public bool Conversation;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
NoBirthAnim = false;
|
||||
EnablePortals = false;
|
||||
PlayHoverAnim = false;
|
||||
MovementUpdate = false;
|
||||
MovementTransport = false;
|
||||
Stationary = false;
|
||||
CombatVictim = false;
|
||||
ServerTime = false;
|
||||
Vehicle = false;
|
||||
AnimKit = false;
|
||||
Rotation = false;
|
||||
AreaTrigger = false;
|
||||
GameObject = false;
|
||||
SmoothPhasing = false;
|
||||
ThisIsYou = false;
|
||||
SceneObject = false;
|
||||
ActivePlayer = false;
|
||||
Conversation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1461,9 +1461,9 @@ namespace Game.Entities
|
||||
return base.GetOwner().ToPlayer();
|
||||
}
|
||||
|
||||
public override void SetDisplayId(uint modelId)
|
||||
public override void SetDisplayId(uint modelId, float displayScale = 1f)
|
||||
{
|
||||
base.SetDisplayId(modelId);
|
||||
base.SetDisplayId(modelId, displayScale);
|
||||
|
||||
if (!isControlled())
|
||||
return;
|
||||
|
||||
@@ -70,14 +70,14 @@ namespace Game.Entities
|
||||
public void LoadToys()
|
||||
{
|
||||
foreach (var value in _toys.Keys)
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Toys, value);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Toys, value);
|
||||
}
|
||||
|
||||
public bool AddToy(uint itemId, bool isFavourite = false)
|
||||
{
|
||||
if (UpdateAccountToys(itemId, isFavourite))
|
||||
{
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Toys, itemId);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Toys, itemId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -198,8 +198,8 @@ namespace Game.Entities
|
||||
{
|
||||
foreach (var item in _heirlooms)
|
||||
{
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Heirlooms, item.Key);
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.HeirloomsFlags, (uint)item.Value.flags);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Heirlooms, item.Key);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, (uint)item.Value.flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,8 +207,8 @@ namespace Game.Entities
|
||||
{
|
||||
if (UpdateAccountHeirlooms(itemId, flags))
|
||||
{
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Heirlooms, itemId);
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.HeirloomsFlags, (uint)flags);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Heirlooms, itemId);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, (uint)flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,10 +249,10 @@ namespace Game.Entities
|
||||
item.AddBonuses(bonusId);
|
||||
|
||||
// Get heirloom offset to update only one part of dynamic field
|
||||
var fields = player.GetDynamicValues(PlayerDynamicFields.Heirlooms);
|
||||
var fields = player.GetDynamicValues(ActivePlayerDynamicFields.Heirlooms);
|
||||
ushort offset = (ushort)Array.IndexOf(fields, itemId);
|
||||
|
||||
player.SetDynamicValue(PlayerDynamicFields.HeirloomsFlags, offset, (uint)flags);
|
||||
player.SetDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, offset, (uint)flags);
|
||||
data.flags = flags;
|
||||
data.bonusId = bonusId;
|
||||
}
|
||||
@@ -292,11 +292,11 @@ namespace Game.Entities
|
||||
|
||||
if (newItemId != 0)
|
||||
{
|
||||
var heirloomFields = player.GetDynamicValues(PlayerDynamicFields.Heirlooms);
|
||||
var heirloomFields = player.GetDynamicValues(ActivePlayerDynamicFields.Heirlooms);
|
||||
ushort offset = (ushort)Array.IndexOf(heirloomFields, item.GetEntry());
|
||||
|
||||
player.SetDynamicValue(PlayerDynamicFields.Heirlooms, offset, newItemId);
|
||||
player.SetDynamicValue(PlayerDynamicFields.HeirloomsFlags, offset, 0);
|
||||
player.SetDynamicValue(ActivePlayerDynamicFields.Heirlooms, offset, newItemId);
|
||||
player.SetDynamicValue(ActivePlayerDynamicFields.HeirloomFlags, offset, 0);
|
||||
|
||||
_heirlooms.Remove(item.GetEntry());
|
||||
_heirlooms[newItemId] = null;
|
||||
@@ -432,11 +432,11 @@ namespace Game.Entities
|
||||
{
|
||||
foreach (uint blockValue in _appearances.ToBlockRange())
|
||||
{
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Transmog, blockValue);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Transmog, blockValue);
|
||||
}
|
||||
|
||||
foreach (var value in _temporaryAppearances.Keys)
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.ConditionalTransmog, value);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, value);
|
||||
}
|
||||
|
||||
public void LoadAccountItemAppearances(SQLResult knownAppearances, SQLResult favoriteAppearances)
|
||||
@@ -661,18 +661,18 @@ namespace Game.Entities
|
||||
_appearances.Length = (int)itemModifiedAppearance.Id + 1;
|
||||
numBlocks = (uint)(_appearances.Count << 2) - numBlocks;
|
||||
while (numBlocks-- != 0)
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.Transmog, 0);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.Transmog, 0);
|
||||
}
|
||||
|
||||
_appearances.Set((int)itemModifiedAppearance.Id, true);
|
||||
uint blockIndex = itemModifiedAppearance.Id / 32;
|
||||
uint bitIndex = itemModifiedAppearance.Id % 32;
|
||||
uint currentMask = _owner.GetPlayer().GetDynamicValue(PlayerDynamicFields.Transmog, (ushort)blockIndex);
|
||||
_owner.GetPlayer().SetDynamicValue(PlayerDynamicFields.Transmog, (ushort)blockIndex, (uint)((int)currentMask | (1 << (int)bitIndex)));
|
||||
uint currentMask = _owner.GetPlayer().GetDynamicValue(ActivePlayerDynamicFields.Transmog, (ushort)blockIndex);
|
||||
_owner.GetPlayer().SetDynamicValue(ActivePlayerDynamicFields.Transmog, (ushort)blockIndex, (uint)((int)currentMask | (1 << (int)bitIndex)));
|
||||
var temporaryAppearance = _temporaryAppearances.LookupByKey(itemModifiedAppearance.Id);
|
||||
if (!temporaryAppearance.Empty())
|
||||
{
|
||||
_owner.GetPlayer().RemoveDynamicValue(PlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
|
||||
_owner.GetPlayer().RemoveDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
|
||||
_temporaryAppearances.Remove(itemModifiedAppearance.Id);
|
||||
}
|
||||
|
||||
@@ -694,7 +694,7 @@ namespace Game.Entities
|
||||
{
|
||||
var itemsWithAppearance = _temporaryAppearances[itemModifiedAppearance.Id];
|
||||
if (itemsWithAppearance.Empty())
|
||||
_owner.GetPlayer().AddDynamicValue(PlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
|
||||
_owner.GetPlayer().AddDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
|
||||
|
||||
itemsWithAppearance.Add(itemGuid);
|
||||
}
|
||||
@@ -712,7 +712,7 @@ namespace Game.Entities
|
||||
guid.Remove(item.GetGUID());
|
||||
if (guid.Empty())
|
||||
{
|
||||
_owner.GetPlayer().RemoveDynamicValue(PlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
|
||||
_owner.GetPlayer().RemoveDynamicValue(ActivePlayerDynamicFields.ConditionalTransmog, itemModifiedAppearance.Id);
|
||||
_temporaryAppearances.Remove(itemModifiedAppearance.Id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace Game.Entities
|
||||
}
|
||||
public float GetRatingBonusValue(CombatRating cr)
|
||||
{
|
||||
float baseResult = GetFloatValue(PlayerFields.CombatRating1 + (int)cr) * GetRatingMultiplier(cr);
|
||||
float baseResult = GetFloatValue(ActivePlayerFields.CombatRating + (int)cr) * GetRatingMultiplier(cr);
|
||||
if (cr != CombatRating.ResiliencePlayerDamage)
|
||||
return baseResult;
|
||||
return (float)(1.0f - Math.Pow(0.99f, baseResult)) * 100.0f;
|
||||
@@ -189,9 +189,9 @@ namespace Game.Entities
|
||||
switch (attType)
|
||||
{
|
||||
case WeaponAttackType.BaseAttack:
|
||||
return baseExpertise + GetUInt32Value(PlayerFields.Expertise) / 4.0f;
|
||||
return baseExpertise + GetUInt32Value(ActivePlayerFields.Expertise) / 4.0f;
|
||||
case WeaponAttackType.OffAttack:
|
||||
return baseExpertise + GetUInt32Value(PlayerFields.OffhandExpertise) / 4.0f;
|
||||
return baseExpertise + GetUInt32Value(ActivePlayerFields.OffhandExpertise) / 4.0f;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -348,7 +348,6 @@ namespace Game.Entities
|
||||
}
|
||||
void _LoadSkills(SQLResult result)
|
||||
{
|
||||
var professionCount = 0;
|
||||
var count = 0;
|
||||
Dictionary<uint, uint> loadedSkillValues = new Dictionary<uint, uint>();
|
||||
if (!result.IsEmpty())
|
||||
@@ -396,7 +395,7 @@ namespace Game.Entities
|
||||
var field = (ushort)(count / 2);
|
||||
var offset = (byte)(count & 1);
|
||||
|
||||
SetUInt16Value(PlayerFields.SkillLineId + field, offset, skill);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, skill);
|
||||
ushort step = 0;
|
||||
|
||||
SkillLineRecord skillLine = CliDB.SkillLineStorage.LookupByKey(rcEntry.SkillID);
|
||||
@@ -409,16 +408,20 @@ namespace Game.Entities
|
||||
{
|
||||
step = (ushort)(max / 75);
|
||||
|
||||
if (professionCount < 2)
|
||||
SetUInt32Value(PlayerFields.ProfessionSkillLine1 + professionCount++, skill);
|
||||
if (skillLine.ParentSkillLineID != 0 && skillLine.ParentTierIndex != 0)
|
||||
{
|
||||
int professionSlot = FindProfessionSlotFor(skill);
|
||||
if (professionSlot != -1)
|
||||
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + professionSlot, skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, step);
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, value);
|
||||
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, max);
|
||||
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, step);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, value);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, max);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
|
||||
mSkillStatus.Add(skill, new SkillStatusData((uint)count, SkillState.Unchanged));
|
||||
|
||||
@@ -445,12 +448,12 @@ namespace Game.Entities
|
||||
var field = (ushort)(count / 2);
|
||||
var offset = (byte)(count & 1);
|
||||
|
||||
SetUInt16Value(PlayerFields.SkillLineId + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
}
|
||||
}
|
||||
void _LoadSpells(SQLResult result)
|
||||
@@ -846,7 +849,7 @@ namespace Game.Entities
|
||||
if (quest == null)
|
||||
continue;
|
||||
|
||||
AddDynamicValue(PlayerDynamicFields.DailyQuests, quest_id);
|
||||
AddDynamicValue(ActivePlayerDynamicFields.DailyQuests, quest_id);
|
||||
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
|
||||
if (questBit != 0)
|
||||
SetQuestCompletedBit(questBit, true);
|
||||
@@ -953,14 +956,17 @@ namespace Game.Entities
|
||||
}
|
||||
void _LoadPvpTalents(SQLResult result)
|
||||
{
|
||||
// "SELECT TalentID, TalentGroup FROM character_pvp_talent WHERE guid = ?"
|
||||
// "SELECT talentID0, talentID1, talentID2, talentID3, talentGroup FROM character_pvp_talent WHERE guid = ?"
|
||||
if (!result.IsEmpty())
|
||||
{
|
||||
do
|
||||
{
|
||||
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(result.Read<uint>(0));
|
||||
if (talent != null)
|
||||
AddPvpTalent(talent, result.Read<byte>(1), false);
|
||||
for (byte slot = 0; slot < PlayerConst.MaxPvpTalentSlots; ++slot)
|
||||
{
|
||||
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(result.Read<uint>(slot));
|
||||
if (talent != null)
|
||||
AddPvpTalent(talent, result.Read<byte>(4), slot);
|
||||
}
|
||||
}
|
||||
while (result.NextRow());
|
||||
}
|
||||
@@ -1000,7 +1006,7 @@ namespace Game.Entities
|
||||
if (!result.IsEmpty() && !HasAtLoginFlag(AtLoginFlags.Resurrect))
|
||||
{
|
||||
_corpseLocation = new WorldLocation(result.Read<ushort>(0), result.Read<float>(1), result.Read<float>(2), result.Read<float>(3), result.Read<float>(4));
|
||||
ApplyModFlag(PlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(_corpseLocation.GetMapId()).Instanceable());
|
||||
ApplyModFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(_corpseLocation.GetMapId()).Instanceable());
|
||||
}
|
||||
else
|
||||
ResurrectPlayer(0.5f);
|
||||
@@ -1576,8 +1582,8 @@ namespace Game.Entities
|
||||
var field = (ushort)(skill.Value.Pos / 2);
|
||||
var offset = (byte)(skill.Value.Pos & 1);
|
||||
|
||||
var value = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
|
||||
var max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
|
||||
var value = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
|
||||
var max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
|
||||
|
||||
switch (skill.Value.State)
|
||||
{
|
||||
@@ -1607,7 +1613,7 @@ namespace Game.Entities
|
||||
{
|
||||
PreparedStatement stmt = null;
|
||||
|
||||
foreach (var spell in m_spells)
|
||||
foreach (var spell in m_spells.ToList())
|
||||
{
|
||||
if (spell.Value.State == PlayerSpellState.Removed || spell.Value.State == PlayerSpellState.Changed)
|
||||
{
|
||||
@@ -1884,7 +1890,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
trans.Append(stmt);
|
||||
|
||||
var dailies = GetDynamicValues(PlayerDynamicFields.DailyQuests);
|
||||
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
|
||||
foreach (var questId in dailies)
|
||||
{
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_QUESTSTATUS_DAILY);
|
||||
@@ -1976,7 +1982,7 @@ namespace Game.Entities
|
||||
|
||||
for (byte group = 0; group < PlayerConst.MaxSpecializations; ++group)
|
||||
{
|
||||
Dictionary<uint, PlayerSpellState> talents = GetTalentMap(group);
|
||||
var talents = GetTalentMap(group);
|
||||
foreach (var pair in talents.ToList())
|
||||
{
|
||||
if (pair.Value == PlayerSpellState.Removed)
|
||||
@@ -1999,21 +2005,15 @@ namespace Game.Entities
|
||||
|
||||
for (byte group = 0; group < PlayerConst.MaxSpecializations; ++group)
|
||||
{
|
||||
Dictionary<uint, PlayerSpellState> talents = GetPvpTalentMap(group);
|
||||
foreach (var pair in talents.ToList())
|
||||
{
|
||||
if (pair.Value == PlayerSpellState.Removed)
|
||||
{
|
||||
talents.Remove(pair.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_PVP_TALENT);
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
stmt.AddValue(1, pair.Key);
|
||||
stmt.AddValue(2, group);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
var talents = GetPvpTalentMap(group);
|
||||
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_PVP_TALENT);
|
||||
stmt.AddValue(0, GetGUID().GetCounter());
|
||||
stmt.AddValue(1, talents[0]);
|
||||
stmt.AddValue(2, talents[1]);
|
||||
stmt.AddValue(3, talents[2]);
|
||||
stmt.AddValue(4, talents[3]);
|
||||
stmt.AddValue(5, group);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
}
|
||||
public void _SaveMail(SQLTransaction trans)
|
||||
@@ -2102,18 +2102,18 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, GetStat((Stats)i));
|
||||
|
||||
for (int i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
stmt.AddValue(index++, GetResistance((SpellSchools)i));
|
||||
stmt.AddValue(index++, GetResistance((SpellSchools)i) + GetBonusResistanceMod((SpellSchools)i));
|
||||
|
||||
stmt.AddValue(index++, GetFloatValue(PlayerFields.BlockPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(PlayerFields.DodgePercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(PlayerFields.ParryPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(PlayerFields.CritPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(PlayerFields.RangedCritPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(PlayerFields.SpellCritPercentage1));
|
||||
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.BlockPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.DodgePercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.ParryPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.CritPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.RangedCritPercentage));
|
||||
stmt.AddValue(index++, GetFloatValue(ActivePlayerFields.SpellCritPercentage1));
|
||||
stmt.AddValue(index++, GetUInt32Value(UnitFields.AttackPower));
|
||||
stmt.AddValue(index++, GetUInt32Value(UnitFields.RangedAttackPower));
|
||||
stmt.AddValue(index++, GetBaseSpellPowerBonus());
|
||||
stmt.AddValue(index, GetUInt32Value(PlayerFields.CombatRating1 + (int)CombatRating.ResiliencePlayerDamage));
|
||||
stmt.AddValue(index, GetUInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.ResiliencePlayerDamage));
|
||||
|
||||
trans.Append(stmt);
|
||||
}
|
||||
@@ -2408,8 +2408,8 @@ namespace Game.Entities
|
||||
SetUInt32Value(UnitFields.Level, result.Read<uint>(6));
|
||||
SetXP(result.Read<uint>(7));
|
||||
|
||||
_LoadIntoDataField(result.Read<string>(66), (int)PlayerFields.ExploredZones1, PlayerConst.ExploredZonesSize);
|
||||
_LoadIntoDataField(result.Read<string>(67), (int)PlayerFields.KnownTitles, PlayerConst.KnowTitlesSize * 2);
|
||||
_LoadIntoDataField(result.Read<string>(66), (int)ActivePlayerFields.ExploredZones, PlayerConst.ExploredZonesSize);
|
||||
_LoadIntoDataField(result.Read<string>(67), (int)ActivePlayerFields.KnownTitles, PlayerConst.KnowTitlesSize * 2);
|
||||
|
||||
SetObjectScale(1.0f);
|
||||
SetFloatValue(UnitFields.HoverHeight, 1.0f);
|
||||
@@ -2441,7 +2441,7 @@ namespace Game.Entities
|
||||
SetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetInebriation, result.Read<byte>(55));
|
||||
SetUInt32Value(PlayerFields.Flags, result.Read<uint>(20));
|
||||
SetUInt32Value(PlayerFields.FlagsEx, result.Read<uint>(21));
|
||||
SetInt32Value(PlayerFields.WatchedFactionIndex, (int)result.Read<uint>(54));
|
||||
SetInt32Value(ActivePlayerFields.WatchedFactionIndex, (int)result.Read<uint>(54));
|
||||
|
||||
if (!ValidateAppearance((Race)result.Read<byte>(3), (Class)result.Read<byte>(4), (Gender)gender,
|
||||
GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetHairStyleId),
|
||||
@@ -2455,7 +2455,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
|
||||
SetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles, result.Read<byte>(68));
|
||||
SetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles, result.Read<byte>(68));
|
||||
|
||||
m_fishingSteps = result.Read<byte>(72);
|
||||
|
||||
@@ -2464,7 +2464,7 @@ namespace Game.Entities
|
||||
// cleanup inventory related item value fields (its will be filled correctly in _LoadInventory)
|
||||
for (byte slot = EquipmentSlot.Start; slot < EquipmentSlot.End; ++slot)
|
||||
{
|
||||
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
|
||||
SetVisibleItemSlot(slot, null);
|
||||
|
||||
m_items[slot] = null;
|
||||
@@ -2518,9 +2518,9 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
_LoadCurrency(holder.GetResult(PlayerLoginQueryLoad.Currency));
|
||||
SetUInt32Value(PlayerFields.LifetimeHonorableKills, result.Read<uint>(50));
|
||||
SetUInt16Value(PlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetTodayKills, result.Read<ushort>(51));
|
||||
SetUInt16Value(PlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetYesterdayKills, result.Read<ushort>(52));
|
||||
SetUInt32Value(ActivePlayerFields.LifetimeHonorableKills, result.Read<uint>(50));
|
||||
SetUInt16Value(ActivePlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetTodayKills, result.Read<ushort>(51));
|
||||
SetUInt16Value(ActivePlayerFields.Kills, PlayerFieldOffsets.FieldKillsOffsetYesterdayKills, result.Read<ushort>(52));
|
||||
|
||||
_LoadBoundInstances(holder.GetResult(PlayerLoginQueryLoad.BoundInstances));
|
||||
_LoadInstanceTimeRestrictions(holder.GetResult(PlayerLoginQueryLoad.InstanceLockTimes));
|
||||
@@ -2843,14 +2843,14 @@ namespace Game.Entities
|
||||
SetGuidValue(UnitFields.CharmedBy, ObjectGuid.Empty);
|
||||
SetGuidValue(UnitFields.Charm, ObjectGuid.Empty);
|
||||
SetGuidValue(UnitFields.Summon, ObjectGuid.Empty);
|
||||
SetGuidValue(PlayerFields.Farsight, ObjectGuid.Empty);
|
||||
SetGuidValue(ActivePlayerFields.Farsight, ObjectGuid.Empty);
|
||||
SetCreatorGUID(ObjectGuid.Empty);
|
||||
|
||||
RemoveFlag(UnitFields.Flags2, UnitFlags2.ForceMove);
|
||||
|
||||
// reset some aura modifiers before aura apply
|
||||
SetUInt32Value(PlayerFields.TrackCreatures, 0);
|
||||
SetUInt32Value(PlayerFields.TrackResources, 0);
|
||||
SetUInt32Value(ActivePlayerFields.TrackCreatures, 0);
|
||||
SetUInt32Value(ActivePlayerFields.TrackResources, 0);
|
||||
|
||||
// make sure the unit is considered out of combat for proper loading
|
||||
ClearInCombat();
|
||||
@@ -3061,7 +3061,7 @@ namespace Game.Entities
|
||||
SetFlag(ObjectFields.DynamicFlags, UnitDynFlags.ReferAFriend);
|
||||
|
||||
if (m_grantableLevels > 0)
|
||||
SetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
|
||||
SetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
|
||||
|
||||
_LoadDeclinedNames(holder.GetResult(PlayerLoginQueryLoad.DeclinedNames));
|
||||
|
||||
@@ -3078,9 +3078,9 @@ namespace Game.Entities
|
||||
holder.GetResult(PlayerLoginQueryLoad.GarrisonFollowerAbilities)))
|
||||
_garrison = garrison;
|
||||
|
||||
_InitHonorLevelOnLoadFromDB(result.Read<uint>(73), result.Read<uint>(74), result.Read<uint>(75));
|
||||
_InitHonorLevelOnLoadFromDB(result.Read<uint>(73), result.Read<uint>(74));
|
||||
|
||||
_restMgr.LoadRestBonus(RestTypes.Honor, (PlayerRestState)result.Read<byte>(76), result.Read<float>(77));
|
||||
_restMgr.LoadRestBonus(RestTypes.Honor, (PlayerRestState)result.Read<byte>(75), result.Read<float>(76));
|
||||
if (time_diff > 0)
|
||||
{
|
||||
//speed collect rest bonus in offline, in logout, far from tavern, city (section/in hour)
|
||||
@@ -3132,7 +3132,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, (byte)GetClass());
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender));
|
||||
stmt.AddValue(index++, getLevel());
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Xp));
|
||||
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.Xp));
|
||||
stmt.AddValue(index++, GetMoney());
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId));
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetFaceId));
|
||||
@@ -3143,7 +3143,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes2, (byte)(PlayerFieldOffsets.Bytes2OffsetCustomDisplayOption + i)));
|
||||
stmt.AddValue(index++, GetInventorySlotCount());
|
||||
stmt.AddValue(index++, GetBankBagSlotCount());
|
||||
stmt.AddValue(index++, (byte)GetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
|
||||
stmt.AddValue(index++, (byte)GetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Flags));
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.FlagsEx));
|
||||
stmt.AddValue(index++, (ushort)GetMapId());
|
||||
@@ -3191,11 +3191,11 @@ namespace Game.Entities
|
||||
ss.Append(m_taxi.SaveTaxiDestinationsToString());
|
||||
|
||||
stmt.AddValue(index++, ss.ToString());
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.LifetimeHonorableKills));
|
||||
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 0));
|
||||
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 1));
|
||||
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.LifetimeHonorableKills));
|
||||
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 0));
|
||||
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 1));
|
||||
stmt.AddValue(index++, (uint)GetInt32Value(PlayerFields.ChosenTitle));
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.WatchedFactionIndex));
|
||||
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.WatchedFactionIndex));
|
||||
stmt.AddValue(index++, GetDrunkValue());
|
||||
stmt.AddValue(index++, GetHealth());
|
||||
|
||||
@@ -3222,7 +3222,7 @@ namespace Game.Entities
|
||||
|
||||
ss.Clear();
|
||||
for (var i = 0; i < PlayerConst.ExploredZonesSize; ++i)
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.ExploredZones1 + i));
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.ExploredZones + i));
|
||||
stmt.AddValue(index++, ss.ToString());
|
||||
|
||||
ss.Clear();
|
||||
@@ -3248,10 +3248,10 @@ namespace Game.Entities
|
||||
|
||||
ss.Clear();
|
||||
for (var i = 0; i < PlayerConst.KnowTitlesSize * 2; ++i)
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.KnownTitles + i));
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.KnownTitles + i));
|
||||
stmt.AddValue(index++, ss.ToString());
|
||||
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
|
||||
stmt.AddValue(index++, GetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
|
||||
stmt.AddValue(index++, m_grantableLevels);
|
||||
stmt.AddValue(index++, Global.WorldMgr.GetRealm().Build);
|
||||
}
|
||||
@@ -3264,7 +3264,7 @@ namespace Game.Entities
|
||||
stmt.AddValue(index++, (byte)GetClass());
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender));
|
||||
stmt.AddValue(index++, getLevel());
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Xp));
|
||||
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.Xp));
|
||||
stmt.AddValue(index++, GetMoney());
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId));
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetFaceId));
|
||||
@@ -3276,7 +3276,7 @@ namespace Game.Entities
|
||||
PlayerFieldOffsets.Bytes2OffsetCustomDisplayOption + i)));
|
||||
stmt.AddValue(index++, GetInventorySlotCount());
|
||||
stmt.AddValue(index++, GetBankBagSlotCount());
|
||||
stmt.AddValue(index++, (byte)GetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
|
||||
stmt.AddValue(index++, (byte)GetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp));
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Flags));
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.FlagsEx));
|
||||
|
||||
@@ -3340,11 +3340,11 @@ namespace Game.Entities
|
||||
ss.Append(m_taxi.SaveTaxiDestinationsToString());
|
||||
|
||||
stmt.AddValue(index++, ss.ToString());
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.LifetimeHonorableKills));
|
||||
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 0));
|
||||
stmt.AddValue(index++, GetUInt16Value(PlayerFields.Kills, 1));
|
||||
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.LifetimeHonorableKills));
|
||||
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 0));
|
||||
stmt.AddValue(index++, GetUInt16Value(ActivePlayerFields.Kills, 1));
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.ChosenTitle));
|
||||
stmt.AddValue(index++, (uint)GetInt32Value(PlayerFields.WatchedFactionIndex));
|
||||
stmt.AddValue(index++, (uint)GetInt32Value(ActivePlayerFields.WatchedFactionIndex));
|
||||
stmt.AddValue(index++, GetDrunkValue());
|
||||
stmt.AddValue(index++, GetHealth());
|
||||
|
||||
@@ -3371,7 +3371,7 @@ namespace Game.Entities
|
||||
|
||||
ss.Clear();
|
||||
for (var i = 0; i < PlayerConst.ExploredZonesSize; ++i)
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.ExploredZones1 + i));
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.ExploredZones + i));
|
||||
stmt.AddValue(index++, ss.ToString());
|
||||
|
||||
ss.Clear();
|
||||
@@ -3397,17 +3397,16 @@ namespace Game.Entities
|
||||
|
||||
ss.Clear();
|
||||
for (var i = 0; i < PlayerConst.KnowTitlesSize * 2; ++i)
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(PlayerFields.KnownTitles + i));
|
||||
ss.AppendFormat("{0} ", GetUInt32Value(ActivePlayerFields.KnownTitles + i));
|
||||
|
||||
stmt.AddValue(index++, ss.ToString());
|
||||
stmt.AddValue(index++, GetByteValue(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
|
||||
stmt.AddValue(index++, GetByteValue(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetActionBarToggles));
|
||||
stmt.AddValue(index++, m_grantableLevels);
|
||||
|
||||
stmt.AddValue(index++, IsInWorld && !GetSession().PlayerLogout() ? 1 : 0);
|
||||
stmt.AddValue(index++, GetUInt32Value(PlayerFields.Honor));
|
||||
stmt.AddValue(index++, GetUInt32Value(ActivePlayerFields.Honor));
|
||||
stmt.AddValue(index++, GetHonorLevel());
|
||||
stmt.AddValue(index++, GetPrestigeLevel());
|
||||
stmt.AddValue(index++, (byte)GetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor));
|
||||
stmt.AddValue(index++, (byte)GetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor));
|
||||
stmt.AddValue(index++, _restMgr.GetRestBonus(RestTypes.Honor));
|
||||
stmt.AddValue(index++, Global.WorldMgr.GetRealm().Build);
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@ namespace Game.Entities
|
||||
ulong m_GuildIdInvited;
|
||||
DeclinedName _declinedname;
|
||||
Runes m_runes = new Runes();
|
||||
uint m_hostileReferenceCheckTimer;
|
||||
uint m_drunkTimer;
|
||||
long m_logintime;
|
||||
long m_Last_tick;
|
||||
@@ -319,13 +320,13 @@ namespace Game.Entities
|
||||
for (byte i = 0; i < PlayerConst.MaxSpecializations; ++i)
|
||||
{
|
||||
Talents[i] = new Dictionary<uint, PlayerSpellState>();
|
||||
PvpTalents[i] = new Dictionary<uint, PlayerSpellState>();
|
||||
PvpTalents[i] = new Array<uint>(PlayerConst.MaxPvpTalentSlots);
|
||||
Glyphs[i] = new List<uint>();
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<uint, PlayerSpellState>[] Talents = new Dictionary<uint, PlayerSpellState>[PlayerConst.MaxSpecializations];
|
||||
public Dictionary<uint, PlayerSpellState>[] PvpTalents = new Dictionary<uint, PlayerSpellState>[PlayerConst.MaxSpecializations];
|
||||
public Array<uint>[] PvpTalents = new Array<uint>[PlayerConst.MaxSpecializations];
|
||||
public List<uint>[] Glyphs = new List<uint>[PlayerConst.MaxSpecializations];
|
||||
public uint ResetTalentsCost;
|
||||
public long ResetTalentsTime;
|
||||
|
||||
@@ -233,6 +233,8 @@ namespace Game.Entities
|
||||
return IsInSameRaidWith(p);
|
||||
case 2:
|
||||
return GetTeam() == p.GetTeam();
|
||||
case 3:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public bool IsInSameGroupWith(Player p)
|
||||
|
||||
@@ -1132,7 +1132,7 @@ namespace Game.Entities
|
||||
if (pBag == null)
|
||||
{
|
||||
m_items[slot] = pItem;
|
||||
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), pItem.GetGUID());
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), pItem.GetGUID());
|
||||
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
|
||||
pItem.SetGuidValue(ItemFields.Owner, GetGUID());
|
||||
|
||||
@@ -1975,7 +1975,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
m_items[slot] = null;
|
||||
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
|
||||
|
||||
if (slot < EquipmentSlot.End)
|
||||
{
|
||||
@@ -3399,7 +3399,7 @@ namespace Game.Entities
|
||||
// if current back slot non-empty search oldest or free
|
||||
if (m_items[slot] != null)
|
||||
{
|
||||
uint oldest_time = GetUInt32Value(PlayerFields.BuyBackTimestamp1);
|
||||
uint oldest_time = GetUInt32Value(ActivePlayerFields.BuyBackTimestamp);
|
||||
uint oldest_slot = InventorySlots.BuyBackStart;
|
||||
|
||||
for (byte i = InventorySlots.BuyBackStart + 1; i < InventorySlots.BuyBackEnd; ++i)
|
||||
@@ -3411,7 +3411,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
|
||||
uint i_time = GetUInt32Value(PlayerFields.BuyBackTimestamp1 + i - InventorySlots.BuyBackStart);
|
||||
uint i_time = GetUInt32Value(ActivePlayerFields.BuyBackTimestamp + i - InventorySlots.BuyBackStart);
|
||||
|
||||
if (oldest_time > i_time)
|
||||
{
|
||||
@@ -3432,13 +3432,13 @@ namespace Game.Entities
|
||||
uint etime = (uint)(time - m_logintime + (30 * 3600));
|
||||
int eslot = (int)slot - InventorySlots.BuyBackStart;
|
||||
|
||||
SetGuidValue(PlayerFields.InvSlotHead + ((int)slot * 4), pItem.GetGUID());
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + ((int)slot * 4), pItem.GetGUID());
|
||||
ItemTemplate proto = pItem.GetTemplate();
|
||||
if (proto != null)
|
||||
SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, proto.GetSellPrice() * pItem.GetCount());
|
||||
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, proto.GetSellPrice() * pItem.GetCount());
|
||||
else
|
||||
SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, 0);
|
||||
SetUInt32Value(PlayerFields.BuyBackTimestamp1 + eslot, etime);
|
||||
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, 0);
|
||||
SetUInt32Value(ActivePlayerFields.BuyBackTimestamp + eslot, etime);
|
||||
|
||||
// move to next (for non filled list is move most optimized choice)
|
||||
if (m_currentBuybackSlot < InventorySlots.BuyBackEnd - 1)
|
||||
@@ -3890,9 +3890,9 @@ namespace Game.Entities
|
||||
m_items[slot] = null;
|
||||
|
||||
int eslot = (int)slot - InventorySlots.BuyBackStart;
|
||||
SetGuidValue(PlayerFields.InvSlotHead + (int)(slot * 4), ObjectGuid.Empty);
|
||||
SetUInt32Value(PlayerFields.BuyBackPrice1 + eslot, 0);
|
||||
SetUInt32Value(PlayerFields.BuyBackTimestamp1 + eslot, 0);
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + (int)(slot * 4), ObjectGuid.Empty);
|
||||
SetUInt32Value(ActivePlayerFields.BuyBackPrice + eslot, 0);
|
||||
SetUInt32Value(ActivePlayerFields.BuyBackTimestamp + eslot, 0);
|
||||
|
||||
// if current backslot is filled set to now free slot
|
||||
if (m_items[m_currentBuybackSlot])
|
||||
@@ -4137,6 +4137,9 @@ namespace Game.Entities
|
||||
case ItemModType.MasteryRating:
|
||||
ApplyRatingMod(CombatRating.Mastery, (int)(val * combatRatingMultiplier), apply);
|
||||
break;
|
||||
case ItemModType.ExtraArmor:
|
||||
HandleStatModifier(UnitMods.Armor, UnitModifierType.TotalValue, (float)val, apply);
|
||||
break;
|
||||
case ItemModType.FireResistance:
|
||||
HandleStatModifier(UnitMods.ResistanceFire, UnitModifierType.BaseValue, (float)val, apply);
|
||||
break;
|
||||
@@ -4219,27 +4222,8 @@ namespace Game.Entities
|
||||
|
||||
uint armor = item.GetArmor(this);
|
||||
if (armor != 0)
|
||||
{
|
||||
UnitModifierType modType = UnitModifierType.TotalValue;
|
||||
if (proto.GetClass() == ItemClass.Armor)
|
||||
{
|
||||
switch ((ItemSubClassArmor)proto.GetSubClass())
|
||||
{
|
||||
case ItemSubClassArmor.Cloth:
|
||||
case ItemSubClassArmor.Leather:
|
||||
case ItemSubClassArmor.Mail:
|
||||
case ItemSubClassArmor.Plate:
|
||||
case ItemSubClassArmor.Shield:
|
||||
modType = UnitModifierType.BaseValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
HandleStatModifier(UnitMods.Armor, modType, armor, apply);
|
||||
}
|
||||
HandleStatModifier(UnitMods.Armor, UnitModifierType.BaseValue, (float)armor, apply);
|
||||
|
||||
//if (proto.GetArmorDamageModifier() > 0)
|
||||
// HandleStatModifier(UnitMods.Armor, UnitModifierType.TotalValue, (float)proto.GetArmorDamageModifier(), apply);
|
||||
|
||||
WeaponAttackType attType = WeaponAttackType.BaseAttack;
|
||||
if (slot == EquipmentSlot.MainHand && (proto.GetInventoryType() == InventoryType.Ranged || proto.GetInventoryType() == InventoryType.RangedRight))
|
||||
{
|
||||
@@ -5617,7 +5601,7 @@ namespace Game.Entities
|
||||
Log.outDebug(LogFilter.Player, "STORAGE: EquipItem slot = {0}, item = {1}", slot, pItem.GetEntry());
|
||||
|
||||
m_items[slot] = pItem;
|
||||
SetGuidValue(PlayerFields.InvSlotHead + (int)(slot * 4), pItem.GetGUID());
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + (int)(slot * 4), pItem.GetGUID());
|
||||
pItem.SetGuidValue(ItemFields.Contained, GetGUID());
|
||||
pItem.SetGuidValue(ItemFields.Owner, GetGUID());
|
||||
pItem.SetSlot((byte)slot);
|
||||
@@ -5661,7 +5645,7 @@ namespace Game.Entities
|
||||
Bag pBag;
|
||||
if (bag == InventorySlots.Bag0)
|
||||
{
|
||||
SetGuidValue(PlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
|
||||
SetGuidValue(ActivePlayerFields.InvSlotHead + (slot * 4), ObjectGuid.Empty);
|
||||
|
||||
// equipment and equipped bags can have applied bonuses
|
||||
if (slot < InventorySlots.BagEnd)
|
||||
@@ -6031,7 +6015,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public byte GetInventorySlotCount() { return GetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots); }
|
||||
public byte GetInventorySlotCount() { return GetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots); }
|
||||
public void SetInventorySlotCount(byte slots)
|
||||
{
|
||||
//ASSERT(slots <= (INVENTORY_SLOT_ITEM_END - INVENTORY_SLOT_ITEM_START));
|
||||
@@ -6074,7 +6058,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
SetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots, slots);
|
||||
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetNumBackpackSlots, slots);
|
||||
}
|
||||
|
||||
public byte GetBankBagSlotCount() { return GetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetBankBagSlots); }
|
||||
@@ -6109,6 +6093,13 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
// dont allow protected item to be looted by someone else
|
||||
if (!item.rollWinnerGUID.IsEmpty() && item.rollWinnerGUID != GetGUID())
|
||||
{
|
||||
SendLootRelease(GetLootGUID());
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemPosCount> dest = new List<ItemPosCount>();
|
||||
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, item.itemid, item.count);
|
||||
if (msg == InventoryResult.Ok)
|
||||
|
||||
@@ -305,7 +305,7 @@ namespace Game.Entities
|
||||
if (save != null)
|
||||
{
|
||||
InstanceBind bind = new InstanceBind();
|
||||
if (m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
|
||||
if (m_boundInstances.ContainsKey(save.GetDifficultyID()) && m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
|
||||
bind = m_boundInstances[save.GetDifficultyID()][save.GetMapId()];
|
||||
|
||||
if (extendState == BindExtensionState.Keep) // special flag, keep the player's current extend state when updating for new boss down
|
||||
@@ -364,6 +364,9 @@ namespace Game.Entities
|
||||
|
||||
Global.ScriptMgr.OnPlayerBindToInstance(this, save.GetDifficultyID(), save.GetMapId(), permanent, extendState);
|
||||
|
||||
if (!m_boundInstances.ContainsKey(save.GetDifficultyID()))
|
||||
m_boundInstances[save.GetDifficultyID()] = new Dictionary<uint, InstanceBind>();
|
||||
|
||||
m_boundInstances[save.GetDifficultyID()][save.GetMapId()] = bind;
|
||||
return bind;
|
||||
}
|
||||
@@ -406,7 +409,7 @@ namespace Game.Entities
|
||||
{
|
||||
InstanceSave save = instanceBind.save;
|
||||
|
||||
InstanceLockInfos lockInfos;
|
||||
InstanceLock lockInfos;
|
||||
lockInfos.InstanceID = save.GetInstanceId();
|
||||
lockInfos.MapID = save.GetMapId();
|
||||
lockInfos.DifficultyID = (uint)save.GetDifficultyID();
|
||||
|
||||
@@ -46,15 +46,15 @@ namespace Game.Entities
|
||||
if (m_lastHonorUpdateTime >= yesterday)
|
||||
{
|
||||
// this is the first update today, reset today's contribution
|
||||
ushort killsToday = GetUInt16Value(PlayerFields.Kills, 0);
|
||||
SetUInt16Value(PlayerFields.Kills, 0, 0);
|
||||
SetUInt16Value(PlayerFields.Kills, 1, killsToday);
|
||||
ushort killsToday = GetUInt16Value(ActivePlayerFields.Kills, 0);
|
||||
SetUInt16Value(ActivePlayerFields.Kills, 0, 0);
|
||||
SetUInt16Value(ActivePlayerFields.Kills, 1, killsToday);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// no honor/kills yesterday or today, reset
|
||||
SetUInt32Value(PlayerFields.Kills, 0);
|
||||
SetUInt32Value(ActivePlayerFields.Kills, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,9 +134,9 @@ namespace Game.Entities
|
||||
honor_f = (float)Math.Ceiling(Formulas.hk_honor_at_level_f(k_level) * (v_level - k_grey) / (k_level - k_grey));
|
||||
|
||||
// count the number of playerkills in one day
|
||||
ApplyModUInt16Value(PlayerFields.Kills, 0, 1, true);
|
||||
ApplyModUInt16Value(ActivePlayerFields.Kills, 0, 1, true);
|
||||
// and those in a lifetime
|
||||
ApplyModUInt32Value(PlayerFields.LifetimeHonorableKills, 1, true);
|
||||
ApplyModUInt32Value(ActivePlayerFields.LifetimeHonorableKills, 1, true);
|
||||
UpdateCriteria(CriteriaTypes.EarnHonorableKill);
|
||||
UpdateCriteria(CriteriaTypes.HkClass, (uint)victim.GetClass());
|
||||
UpdateCriteria(CriteriaTypes.HkRace, (uint)victim.GetRace());
|
||||
@@ -215,15 +215,12 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
void _InitHonorLevelOnLoadFromDB(uint honor, uint honorLevel, uint prestigeLevel)
|
||||
void _InitHonorLevelOnLoadFromDB(uint honor, uint honorLevel)
|
||||
{
|
||||
SetUInt32Value(PlayerFields.HonorLevel, honorLevel);
|
||||
SetUInt32Value(PlayerFields.Prestige, prestigeLevel);
|
||||
UpdateHonorNextLevel();
|
||||
|
||||
AddHonorXP(honor);
|
||||
if (CanPrestige())
|
||||
Prestige();
|
||||
}
|
||||
|
||||
void RewardPlayerWithRewardPack(uint rewardPackID)
|
||||
@@ -253,12 +250,12 @@ namespace Game.Entities
|
||||
|
||||
public void AddHonorXP(uint xp)
|
||||
{
|
||||
uint currentHonorXP = GetUInt32Value(PlayerFields.Honor);
|
||||
uint nextHonorLevelXP = GetUInt32Value(PlayerFields.HonorNextLevel);
|
||||
uint currentHonorXP = GetUInt32Value(ActivePlayerFields.Honor);
|
||||
uint nextHonorLevelXP = GetUInt32Value(ActivePlayerFields.HonorNextLevel);
|
||||
uint newHonorXP = currentHonorXP + xp;
|
||||
uint honorLevel = GetHonorLevel();
|
||||
|
||||
if (xp < 1 || getLevel() < PlayerConst.LevelMinHonor || IsMaxHonorLevelAndPrestige())
|
||||
if (xp < 1 || getLevel() < PlayerConst.LevelMinHonor || IsMaxHonorLevel())
|
||||
return;
|
||||
|
||||
while (newHonorXP >= nextHonorLevelXP)
|
||||
@@ -269,72 +266,34 @@ namespace Game.Entities
|
||||
SetHonorLevel((byte)(honorLevel + 1));
|
||||
|
||||
honorLevel = GetHonorLevel();
|
||||
nextHonorLevelXP = GetUInt32Value(PlayerFields.HonorNextLevel);
|
||||
nextHonorLevelXP = GetUInt32Value(ActivePlayerFields.HonorNextLevel);
|
||||
}
|
||||
|
||||
SetUInt32Value(PlayerFields.Honor, IsMaxHonorLevelAndPrestige() ? 0 : newHonorXP);
|
||||
SetUInt32Value(ActivePlayerFields.Honor, IsMaxHonorLevel() ? 0 : newHonorXP);
|
||||
}
|
||||
|
||||
void SetHonorLevel(byte level)
|
||||
{
|
||||
byte oldHonorLevel = (byte)GetHonorLevel();
|
||||
byte prestige = (byte)GetPrestigeLevel();
|
||||
if (level == oldHonorLevel)
|
||||
return;
|
||||
|
||||
uint rewardPackID = Global.DB2Mgr.GetRewardPackIDForPvpRewardByHonorLevelAndPrestige(level, prestige);
|
||||
RewardPlayerWithRewardPack(rewardPackID);
|
||||
|
||||
SetUInt32Value(PlayerFields.HonorLevel, level);
|
||||
UpdateHonorNextLevel();
|
||||
|
||||
UpdateCriteria(CriteriaTypes.HonorLevelReached);
|
||||
|
||||
// This code is here because no link was found between those items and this reward condition in the db2 files.
|
||||
// Interesting CriteriaTree found: Tree ids: 51140, 51156 (criteria id 31773, modifier tree id 37759)
|
||||
if (level == 50 && prestige == 1)
|
||||
{
|
||||
if (GetTeam() == Team.Alliance)
|
||||
AddItem(138992, 1);
|
||||
else
|
||||
AddItem(138996, 1);
|
||||
}
|
||||
|
||||
if (CanPrestige())
|
||||
Prestige();
|
||||
}
|
||||
|
||||
public void Prestige()
|
||||
{
|
||||
SetUInt32Value(PlayerFields.Prestige, GetPrestigeLevel() + 1);
|
||||
SetUInt32Value(PlayerFields.HonorLevel, 1);
|
||||
UpdateHonorNextLevel();
|
||||
|
||||
UpdateCriteria(CriteriaTypes.PrestigeReached);
|
||||
}
|
||||
|
||||
public bool CanPrestige()
|
||||
{
|
||||
if (GetSession().GetExpansion() >= Expansion.Legion && getLevel() >= PlayerConst.LevelMinHonor && GetHonorLevel() >= PlayerConst.MaxHonorLevel && GetPrestigeLevel() < Global.DB2Mgr.GetMaxPrestige())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMaxPrestige()
|
||||
{
|
||||
return GetPrestigeLevel() == Global.DB2Mgr.GetMaxPrestige();
|
||||
}
|
||||
|
||||
void UpdateHonorNextLevel()
|
||||
{
|
||||
uint prestige = Math.Min(16 - 1, GetPrestigeLevel());
|
||||
SetUInt32Value(PlayerFields.HonorNextLevel, (uint)CliDB.HonorLevelGameTable.GetRow(GetHonorLevel()).Prestige[prestige]);
|
||||
// 5500 at honor level 1
|
||||
// no idea what between here
|
||||
// 8800 at honor level ~14 (never goes above 8800)
|
||||
SetUInt32Value(ActivePlayerFields.HonorNextLevel, 8800);
|
||||
}
|
||||
|
||||
public uint GetPrestigeLevel() { return GetUInt32Value(PlayerFields.Prestige); }
|
||||
public uint GetHonorLevel() { return GetUInt32Value(PlayerFields.HonorLevel); }
|
||||
public bool IsMaxHonorLevelAndPrestige() { return IsMaxPrestige() && GetHonorLevel() == PlayerConst.MaxHonorLevel; }
|
||||
public bool IsMaxHonorLevel() { return GetHonorLevel() == PlayerConst.MaxHonorLevel; }
|
||||
|
||||
public void ActivatePvpItemLevels(bool activate) { _usePvpItemLevels = activate; }
|
||||
public bool IsUsingPvpItemLevels() { return _usePvpItemLevels; }
|
||||
@@ -343,7 +302,7 @@ namespace Game.Entities
|
||||
{
|
||||
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
|
||||
{
|
||||
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
|
||||
if (talentInfo == null)
|
||||
continue;
|
||||
|
||||
RemovePvpTalent(talentInfo);
|
||||
@@ -355,62 +314,61 @@ namespace Game.Entities
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
public TalentLearnResult LearnPvpTalent(uint talentID, ref uint spellOnCooldown)
|
||||
public TalentLearnResult LearnPvpTalent(uint talentID, byte slot, ref uint spellOnCooldown)
|
||||
{
|
||||
if (slot >= PlayerConst.MaxPvpTalentSlots)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (IsInCombat())
|
||||
return TalentLearnResult.FailedAffectingCombat;
|
||||
|
||||
if (getLevel() < PlayerConst.LevelMinHonor)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
if (IsDead())
|
||||
return TalentLearnResult.FailedCantDoThatRightNow;
|
||||
|
||||
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(talentID);
|
||||
if (talentInfo == null)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (talentInfo.SpecID != 0)
|
||||
{
|
||||
if (talentInfo.SpecID != GetInt32Value(PlayerFields.CurrentSpecId))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
}
|
||||
else if (talentInfo.Role < 7)
|
||||
{
|
||||
if (talentInfo.Role != CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId)).Role)
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
}
|
||||
|
||||
// prevent learn talent for different class (cheating)
|
||||
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
|
||||
if (talentInfo.SpecID != GetInt32Value(PlayerFields.CurrentSpecId))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (GetPrestigeLevel() == 0)
|
||||
if (Global.DB2Mgr.GetRequiredHonorLevelForPvpTalent(talentInfo) > GetHonorLevel())
|
||||
if (talentInfo.LevelRequired > getLevel())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
if (Global.DB2Mgr.GetRequiredLevelForPvpTalentSlot(slot, GetClass()) > getLevel())
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
PvpTalentCategoryRecord talentCategory = CliDB.PvpTalentCategoryStorage.LookupByKey(talentInfo.PvpTalentCategoryID);
|
||||
if (talentCategory != null)
|
||||
if (!Convert.ToBoolean(talentCategory.TalentSlotMask & (1 << slot)))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
// Check if player doesn't have any talent in current tier
|
||||
for (uint c = 0; c < PlayerConst.MaxPvpTalentColumns; ++c)
|
||||
// Check if player doesn't have this talent in other slot
|
||||
if (HasPvpTalent(talentID, GetActiveTalentGroup()))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
PvpTalentRecord talent = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
|
||||
if (talent != null)
|
||||
{
|
||||
foreach (PvpTalentRecord talent in Global.DB2Mgr.GetPvpTalentsByPosition((uint)GetClass(), (uint)talentInfo.TierID, c))
|
||||
if (!HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && !HasFlag(UnitFields.Flags2, UnitFlags2.AllowChangingTalents))
|
||||
return TalentLearnResult.FailedRestArea;
|
||||
|
||||
if (GetSpellHistory().HasCooldown(talent.SpellID))
|
||||
{
|
||||
if (HasPvpTalent(talent.Id, GetActiveTalentGroup()) && !HasFlag(PlayerFields.Flags, PlayerFlags.Resting) && HasFlag(UnitFields.Flags, UnitFlags.ImmuneToNpc))
|
||||
return TalentLearnResult.FailedRestArea;
|
||||
|
||||
if (GetSpellHistory().HasCooldown(talent.SpellID))
|
||||
{
|
||||
spellOnCooldown = talent.SpellID;
|
||||
return TalentLearnResult.FailedCantRemoveTalent;
|
||||
}
|
||||
|
||||
RemovePvpTalent(talent);
|
||||
spellOnCooldown = talent.SpellID;
|
||||
return TalentLearnResult.FailedCantRemoveTalent;
|
||||
}
|
||||
|
||||
RemovePvpTalent(talent);
|
||||
}
|
||||
|
||||
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), true))
|
||||
if (!AddPvpTalent(talentInfo, GetActiveTalentGroup(), slot))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
return TalentLearnResult.LearnOk;
|
||||
}
|
||||
|
||||
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, bool learning)
|
||||
bool AddPvpTalent(PvpTalentRecord talent, byte activeTalentGroup, byte slot)
|
||||
{
|
||||
//ASSERT(talent);
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talent.SpellID);
|
||||
@@ -433,10 +391,7 @@ namespace Game.Entities
|
||||
if (talent.OverridesSpellID != 0)
|
||||
AddOverrideSpell(talent.OverridesSpellID, talent.SpellID);
|
||||
|
||||
if (learning)
|
||||
GetPvpTalentMap(activeTalentGroup)[talent.Id] = PlayerSpellState.New;
|
||||
else
|
||||
GetPvpTalentMap(activeTalentGroup)[talent.Id] = PlayerSpellState.Unchanged;
|
||||
GetPvpTalentMap(activeTalentGroup)[slot] = talent.Id;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -453,27 +408,30 @@ namespace Game.Entities
|
||||
if (talent.OverridesSpellID != 0)
|
||||
RemoveOverrideSpell(talent.OverridesSpellID, talent.SpellID);
|
||||
|
||||
//todo check this
|
||||
// if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted
|
||||
if (!GetPvpTalentMap(GetActiveTalentGroup()).ContainsKey(talent.Id))
|
||||
GetPvpTalentMap(GetActiveTalentGroup())[talent.Id] = PlayerSpellState.Removed;
|
||||
GetPvpTalentMap(GetActiveTalentGroup()).Remove(talent.Id);
|
||||
}
|
||||
|
||||
public void TogglePvpTalents(bool enable)
|
||||
{
|
||||
var pvpTalents = GetPvpTalentMap(GetActiveTalentGroup());
|
||||
foreach (var pair in pvpTalents)
|
||||
foreach (uint pvpTalentId in pvpTalents)
|
||||
{
|
||||
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pair.Key);
|
||||
if (enable && pair.Value != PlayerSpellState.Removed)
|
||||
LearnSpell(pvpTalentInfo.SpellID, false);
|
||||
else
|
||||
RemoveSpell(pvpTalentInfo.SpellID, true);
|
||||
PvpTalentRecord pvpTalentInfo = CliDB.PvpTalentStorage.LookupByKey(pvpTalentId);
|
||||
if (pvpTalentInfo != null)
|
||||
{
|
||||
if (enable)
|
||||
LearnSpell(pvpTalentInfo.SpellID, false);
|
||||
else
|
||||
RemoveSpell(pvpTalentInfo.SpellID, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasPvpTalent(uint talentID, byte activeTalentGroup)
|
||||
{
|
||||
return GetPvpTalentMap(activeTalentGroup).ContainsKey(talentID) && GetPvpTalentMap(activeTalentGroup)[talentID] != PlayerSpellState.Removed;
|
||||
return GetPvpTalentMap(activeTalentGroup).Contains(talentID);
|
||||
}
|
||||
|
||||
public void EnablePvpRules(bool dueToCombat = false)
|
||||
@@ -554,7 +512,7 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
public Dictionary<uint, PlayerSpellState> GetPvpTalentMap(uint spec) { return _specializationInfo.PvpTalents[spec]; }
|
||||
public Array<uint> GetPvpTalentMap(byte spec) { return _specializationInfo.PvpTalents[spec]; }
|
||||
|
||||
//BGs
|
||||
public Battleground GetBattleground()
|
||||
@@ -913,7 +871,7 @@ namespace Game.Entities
|
||||
//Arenas
|
||||
public void SetArenaTeamInfoField(byte slot, ArenaTeamInfoType type, uint value)
|
||||
{
|
||||
SetUInt32Value(PlayerFields.ArenaTeamInfo11 + (slot * (int)ArenaTeamInfoType.End) + (int)type, value);
|
||||
SetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)type, value);
|
||||
}
|
||||
|
||||
public void SetInArenaTeam(uint ArenaTeamId, byte slot, byte type)
|
||||
@@ -956,8 +914,8 @@ namespace Game.Entities
|
||||
}
|
||||
while (result.NextRow());
|
||||
}
|
||||
public uint GetArenaTeamId(byte slot) { return GetUInt32Value(PlayerFields.ArenaTeamInfo11 + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.Id); }
|
||||
public uint GetArenaPersonalRating(byte slot) { return GetUInt32Value(PlayerFields.ArenaTeamInfo11 + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.PersonalRating); }
|
||||
public uint GetArenaTeamId(byte slot) { return GetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.Id); }
|
||||
public uint GetArenaPersonalRating(byte slot) { return GetUInt32Value(ActivePlayerFields.ArenaTeamInfo + (slot * (int)ArenaTeamInfoType.End) + (int)ArenaTeamInfoType.PersonalRating); }
|
||||
public void SetArenaTeamIdInvited(uint ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; }
|
||||
public uint GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; }
|
||||
public uint GetRBGPersonalRating() { return 0; }
|
||||
|
||||
@@ -44,6 +44,35 @@ namespace Game.Entities
|
||||
public List<uint> getRewardedQuests() { return m_RewardedQuests; }
|
||||
Dictionary<uint, QuestStatusData> getQuestStatusMap() { return m_QuestStatus; }
|
||||
|
||||
public int GetQuestMinLevel(Quest quest)
|
||||
{
|
||||
if (quest.Level == -1 && quest.ScalingFactionGroup != 0)
|
||||
{
|
||||
ChrRacesRecord race = CliDB.ChrRacesStorage.LookupByKey(GetRace());
|
||||
FactionTemplateRecord raceFaction = CliDB.FactionTemplateStorage.LookupByKey(race.FactionID);
|
||||
if (raceFaction == null || raceFaction.FactionGroup != quest.ScalingFactionGroup)
|
||||
return quest.MaxScalingLevel;
|
||||
}
|
||||
return quest.MinLevel;
|
||||
}
|
||||
|
||||
public int GetQuestLevel(Quest quest)
|
||||
{
|
||||
if (quest == null)
|
||||
return 0;
|
||||
|
||||
if (quest.Level == -1)
|
||||
{
|
||||
int minLevel = GetQuestMinLevel(quest);
|
||||
int maxLevel = quest.MaxScalingLevel;
|
||||
int level = (int)getLevel();
|
||||
if (level >= minLevel)
|
||||
return Math.Min(level, maxLevel);
|
||||
return minLevel;
|
||||
}
|
||||
return quest.Level;
|
||||
}
|
||||
|
||||
public int GetRewardedQuestCount() { return m_RewardedQuests.Count; }
|
||||
|
||||
public void LearnQuestRewardedSpells(Quest quest)
|
||||
@@ -116,7 +145,7 @@ namespace Game.Entities
|
||||
|
||||
public void DailyReset()
|
||||
{
|
||||
foreach (uint questId in GetDynamicValues(PlayerDynamicFields.DailyQuests))
|
||||
foreach (uint questId in GetDynamicValues(ActivePlayerDynamicFields.DailyQuests))
|
||||
{
|
||||
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
|
||||
if (questBit != 0)
|
||||
@@ -124,10 +153,10 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
DailyQuestsReset dailyQuestsReset = new DailyQuestsReset();
|
||||
dailyQuestsReset.Count = GetDynamicValues(PlayerDynamicFields.DailyQuests).Length;
|
||||
dailyQuestsReset.Count = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests).Length;
|
||||
SendPacket(dailyQuestsReset);
|
||||
|
||||
ClearDynamicValue(PlayerDynamicFields.DailyQuests);
|
||||
ClearDynamicValue(ActivePlayerDynamicFields.DailyQuests);
|
||||
|
||||
m_DFQuests.Clear(); // Dungeon Finder Quests.
|
||||
|
||||
@@ -210,14 +239,6 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
public uint GetQuestLevel(Quest quest)
|
||||
{
|
||||
if (quest == null)
|
||||
return getLevel();
|
||||
|
||||
return (uint)(quest.Level > 0 ? quest.Level : Math.Min((int)getLevel(), quest.MaxScalingLevel));
|
||||
}
|
||||
|
||||
public bool IsQuestRewarded(uint quest_id)
|
||||
{
|
||||
return m_RewardedQuests.Contains(quest_id);
|
||||
@@ -389,7 +410,7 @@ namespace Game.Entities
|
||||
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
|
||||
SatisfyQuestMonth(quest, false) && SatisfyQuestSeasonal(quest, false))
|
||||
{
|
||||
return getLevel() + WorldConfig.GetIntValue(WorldCfg.QuestHighLevelHideDiff) >= quest.MinLevel;
|
||||
return getLevel() + WorldConfig.GetIntValue(WorldCfg.QuestHighLevelHideDiff) >= GetQuestMinLevel(quest);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -796,7 +817,7 @@ namespace Game.Entities
|
||||
|
||||
public uint GetQuestMoneyReward(Quest quest)
|
||||
{
|
||||
return (uint)(quest.MoneyValue(getLevel()) * WorldConfig.GetFloatValue(WorldCfg.RateMoneyQuest));
|
||||
return (uint)(quest.MoneyValue(this) * WorldConfig.GetFloatValue(WorldCfg.RateMoneyQuest));
|
||||
}
|
||||
|
||||
public uint GetQuestXPReward(Quest quest)
|
||||
@@ -807,7 +828,7 @@ namespace Game.Entities
|
||||
if (rewarded && !quest.IsDFQuest())
|
||||
return 0;
|
||||
|
||||
uint XP = (uint)(quest.XPValue(getLevel()) * WorldConfig.GetFloatValue(WorldCfg.RateXpQuest));
|
||||
uint XP = (uint)(quest.XPValue(this) * WorldConfig.GetFloatValue(WorldCfg.RateXpQuest));
|
||||
|
||||
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
|
||||
var ModXPPctAuras = GetAuraEffectsByType(AuraType.ModXpQuestPct);
|
||||
@@ -1231,7 +1252,7 @@ namespace Game.Entities
|
||||
|
||||
public bool SatisfyQuestLevel(Quest qInfo, bool msg)
|
||||
{
|
||||
if (getLevel() < qInfo.MinLevel)
|
||||
if (getLevel() < GetQuestMinLevel(qInfo))
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
@@ -1588,7 +1609,7 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
var dailies = GetDynamicValues(PlayerDynamicFields.DailyQuests);
|
||||
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
|
||||
foreach (var dailyQuestId in dailies)
|
||||
if (dailyQuestId == qInfo.Id)
|
||||
return false;
|
||||
@@ -2018,7 +2039,7 @@ namespace Game.Entities
|
||||
if (fieldOffset >= PlayerConst.QuestsCompletedBitsSize)
|
||||
return;
|
||||
|
||||
ApplyModFlag(PlayerFields.QuestCompleted + fieldOffset, (uint)(1 << (((int)questBit - 1) & 31)), completed);
|
||||
ApplyModFlag(ActivePlayerFields.QuestCompleted + fieldOffset, (uint)(1 << (((int)questBit - 1) & 31)), completed);
|
||||
}
|
||||
|
||||
public void AreaExploredOrEventHappens(uint questId)
|
||||
@@ -2993,7 +3014,7 @@ namespace Game.Entities
|
||||
{
|
||||
if (!qQuest.IsDFQuest())
|
||||
{
|
||||
AddDynamicValue(PlayerDynamicFields.DailyQuests, quest_id);
|
||||
AddDynamicValue(ActivePlayerDynamicFields.DailyQuests, quest_id);
|
||||
m_lastDailyQuestTime = Time.UnixTime; // last daily quest time
|
||||
m_DailyQuestChanged = true;
|
||||
|
||||
@@ -3012,7 +3033,7 @@ namespace Game.Entities
|
||||
bool found = false;
|
||||
if (Global.ObjectMgr.GetQuestTemplate(quest_id) != null)
|
||||
{
|
||||
var dailies = GetDynamicValues(PlayerDynamicFields.DailyQuests);
|
||||
var dailies = GetDynamicValues(ActivePlayerDynamicFields.DailyQuests);
|
||||
foreach (uint dailyQuestId in dailies)
|
||||
{
|
||||
if (dailyQuestId == quest_id)
|
||||
|
||||
@@ -48,20 +48,20 @@ namespace Game.Entities
|
||||
|
||||
if (Global.SpellMgr.GetSkillRangeType(rcEntry) == SkillRangeType.Level)
|
||||
{
|
||||
ushort max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
|
||||
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
|
||||
|
||||
// update only level dependent max skill values
|
||||
if (max != 1)
|
||||
{
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, maxSkill);
|
||||
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, maxSkill);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, maxSkill);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, maxSkill);
|
||||
if (pair.Value.State != SkillState.New)
|
||||
pair.Value.State = SkillState.Changed;
|
||||
}
|
||||
}
|
||||
|
||||
// Update level dependent skillline spells
|
||||
LearnSkillRewardedSpells(rcEntry.SkillID, GetUInt16Value(PlayerFields.SkillLineRank + field, offset));
|
||||
LearnSkillRewardedSpells(rcEntry.SkillID, GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,10 +86,10 @@ namespace Game.Entities
|
||||
ushort field = (ushort)(skill.Value.Pos / 2);
|
||||
byte offset = (byte)(skill.Value.Pos & 1);
|
||||
|
||||
ushort max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
|
||||
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
|
||||
if (max > 1)
|
||||
{
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, max);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, max);
|
||||
|
||||
if (skill.Value.State != SkillState.New)
|
||||
skill.Value.State = SkillState.Changed;
|
||||
@@ -109,9 +109,9 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
int result = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
|
||||
result += GetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset);
|
||||
result += GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
|
||||
int result = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
|
||||
result += GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
|
||||
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
|
||||
return (ushort)(result < 0 ? 0 : result);
|
||||
}
|
||||
|
||||
@@ -127,9 +127,9 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
int result = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
|
||||
result += GetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset);
|
||||
result += GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
|
||||
int result = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
|
||||
result += GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
|
||||
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
|
||||
return (ushort)(result < 0 ? 0 : result);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
return GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
|
||||
return GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
|
||||
}
|
||||
|
||||
public ushort GetSkillStep(SkillType skill)
|
||||
@@ -160,7 +160,7 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
return GetUInt16Value(PlayerFields.SkillLineStep + field, offset);
|
||||
return GetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset);
|
||||
}
|
||||
|
||||
public ushort GetPureMaxSkillValue(SkillType skill)
|
||||
@@ -175,7 +175,7 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
return GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
|
||||
return GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
|
||||
}
|
||||
|
||||
public ushort GetBaseSkillValue(SkillType skill)
|
||||
@@ -190,8 +190,8 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
var result = (int)GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
|
||||
result += GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
|
||||
var result = (int)GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
|
||||
result += GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
|
||||
return (ushort)(result < 0 ? 0 : result);
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
return GetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset);
|
||||
return GetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset);
|
||||
}
|
||||
|
||||
public ushort GetSkillTempBonusValue(uint skill)
|
||||
@@ -222,12 +222,12 @@ namespace Game.Entities
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
return GetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset);
|
||||
return GetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset);
|
||||
}
|
||||
|
||||
void InitializeSelfResurrectionSpells()
|
||||
{
|
||||
ClearDynamicValue(PlayerDynamicFields.SelfResSpells);
|
||||
ClearDynamicValue(ActivePlayerDynamicFields.SelfResSpells);
|
||||
|
||||
uint[] spells = new uint[3];
|
||||
|
||||
@@ -248,7 +248,7 @@ namespace Game.Entities
|
||||
|
||||
foreach (uint selfResSpell in spells)
|
||||
if (selfResSpell != 0)
|
||||
AddDynamicValue(PlayerDynamicFields.SelfResSpells, selfResSpell);
|
||||
AddDynamicValue(ActivePlayerDynamicFields.SelfResSpells, selfResSpell);
|
||||
}
|
||||
|
||||
public void PetSpellInitialize()
|
||||
@@ -415,8 +415,7 @@ namespace Game.Entities
|
||||
// levels sync. with spell requirement for skill levels to learn
|
||||
// bonus abilities in sSkillLineAbilityStore
|
||||
// Used only to avoid scan DBC at each skill grow
|
||||
uint[] bonusSkillLevels = { 75, 150, 225, 300, 375, 450, 525 };
|
||||
int bonusSkillLevelsSize = bonusSkillLevels.Length / sizeof(uint);
|
||||
uint[] bonusSkillLevels = { 75, 150, 225, 300, 375, 450, 525, 600, 700, 850 };
|
||||
|
||||
Log.outDebug(LogFilter.Player, "UpdateSkillPro(SkillId {0}, Chance {0:D3}%)", skillId, chance / 10.0f);
|
||||
if (skillId == 0)
|
||||
@@ -435,8 +434,8 @@ namespace Game.Entities
|
||||
ushort field = (ushort)(skillStatusData.Pos / 2);
|
||||
byte offset = (byte)(skillStatusData.Pos & 1);
|
||||
|
||||
ushort value = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
|
||||
ushort max = GetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset);
|
||||
ushort value = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
|
||||
ushort max = GetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset);
|
||||
|
||||
if (max == 0 || value == 0 || value >= max)
|
||||
return false;
|
||||
@@ -451,13 +450,12 @@ namespace Game.Entities
|
||||
if (new_value > max)
|
||||
new_value = max;
|
||||
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, new_value);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, new_value);
|
||||
if (skillStatusData.State != SkillState.New)
|
||||
skillStatusData.State = SkillState.Changed;
|
||||
|
||||
for (int i = 0; i < bonusSkillLevelsSize; ++i)
|
||||
foreach (uint bsl in bonusSkillLevels)
|
||||
{
|
||||
uint bsl = bonusSkillLevels[i];
|
||||
if (value < bsl && new_value >= bsl)
|
||||
{
|
||||
LearnSkillRewardedSpells(skillId, new_value);
|
||||
@@ -941,7 +939,7 @@ namespace Game.Entities
|
||||
if (skill == null || skill.State == SkillState.Deleted)
|
||||
return;
|
||||
|
||||
int field = (int)(skill.Pos / 2 + (talent ? PlayerFields.SkillLinePermBonus : PlayerFields.SkillLineTempBonus));
|
||||
int field = (int)(skill.Pos / 2 + (talent ? ActivePlayerFields.SkillLinePermBonus : ActivePlayerFields.SkillLineTempBonus));
|
||||
byte offset = (byte)(skill.Pos & 1);
|
||||
|
||||
ushort bonus = GetUInt16Value(field, offset);
|
||||
@@ -1125,7 +1123,7 @@ namespace Game.Entities
|
||||
{
|
||||
var field = (ushort)(skillStatusData.Pos / 2);
|
||||
var offset = (byte)(skillStatusData.Pos & 1);
|
||||
currVal = GetUInt16Value(PlayerFields.SkillLineRank + field, offset);
|
||||
currVal = GetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset);
|
||||
if (newVal != 0)
|
||||
{
|
||||
// if skill value is going down, update enchantments before setting the new value
|
||||
@@ -1133,10 +1131,10 @@ namespace Game.Entities
|
||||
UpdateSkillEnchantments(id, currVal, (ushort)newVal);
|
||||
|
||||
// update step
|
||||
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, (ushort)step);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, (ushort)step);
|
||||
// update value
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, (ushort)newVal);
|
||||
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, (ushort)newVal);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
|
||||
|
||||
if (skillStatusData.State != SkillState.New)
|
||||
skillStatusData.State = SkillState.Changed;
|
||||
@@ -1154,12 +1152,12 @@ namespace Game.Entities
|
||||
//remove enchantments needing this skill
|
||||
UpdateSkillEnchantments(id, currVal, 0);
|
||||
// clear skill fields
|
||||
SetUInt16Value(PlayerFields.SkillLineId + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
|
||||
// mark as deleted or simply remove from map if not saved yet
|
||||
if (skillStatusData.State != SkillState.New)
|
||||
@@ -1168,15 +1166,21 @@ namespace Game.Entities
|
||||
mSkillStatus.Remove(id);
|
||||
|
||||
// remove all spells that related to this skill
|
||||
foreach (var pAbility in CliDB.SkillLineAbilityStorage.Values)
|
||||
if (pAbility.SkillLine == id)
|
||||
RemoveSpell(Global.SpellMgr.GetFirstSpellInChain(pAbility.Spell));
|
||||
List<SkillLineAbilityRecord> skillLineAbilities = Global.DB2Mgr.GetSkillLineAbilitiesBySkill(id);
|
||||
foreach (SkillLineAbilityRecord skillLineAbility in skillLineAbilities)
|
||||
RemoveSpell(Global.SpellMgr.GetFirstSpellInChain(skillLineAbility.Spell));
|
||||
|
||||
foreach (SkillLineRecord childSkillLine in CliDB.SkillLineStorage.Values)
|
||||
{
|
||||
if (childSkillLine.ParentSkillLineID == id)
|
||||
SetSkill(childSkillLine.Id, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Clear profession lines
|
||||
if (GetUInt32Value(PlayerFields.ProfessionSkillLine1) == id)
|
||||
SetUInt32Value(PlayerFields.ProfessionSkillLine1, 0);
|
||||
else if (GetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1) == id)
|
||||
SetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1, 0);
|
||||
if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine) == id)
|
||||
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine, 0);
|
||||
else if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1) == id)
|
||||
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1, 0);
|
||||
}
|
||||
}
|
||||
else if (newVal != 0) //add
|
||||
@@ -1186,7 +1190,7 @@ namespace Game.Entities
|
||||
{
|
||||
var field = (ushort)(i / 2);
|
||||
var offset = (byte)(i & 1);
|
||||
if (GetUInt16Value(PlayerFields.SkillLineId + field, offset) == 0)
|
||||
if (GetUInt16Value(ActivePlayerFields.SkillLineId + field, offset) == 0)
|
||||
{
|
||||
var skillEntry = CliDB.SkillLineStorage.LookupByKey(id);
|
||||
if (skillEntry == null)
|
||||
@@ -1195,18 +1199,31 @@ namespace Game.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
SetUInt16Value(PlayerFields.SkillLineId + field, offset, (ushort)id);
|
||||
if (skillEntry.CategoryID == SkillCategory.Profession)
|
||||
|
||||
if (skillEntry.ParentSkillLineID != 0 && skillEntry.ParentTierIndex > 0)
|
||||
{
|
||||
if (GetUInt32Value(PlayerFields.ProfessionSkillLine1) == 0)
|
||||
SetUInt32Value(PlayerFields.ProfessionSkillLine1, id);
|
||||
else if (GetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1) == 0)
|
||||
SetUInt32Value(PlayerFields.ProfessionSkillLine1 + 1, id);
|
||||
SkillRaceClassInfoRecord rcEntry = Global.DB2Mgr.GetSkillRaceClassInfo(skillEntry.ParentSkillLineID, GetRace(), GetClass());
|
||||
if (rcEntry != null)
|
||||
{
|
||||
SkillTiersEntry tier = Global.ObjectMgr.GetSkillTier(rcEntry.SkillTierID);
|
||||
if (tier != null)
|
||||
{
|
||||
ushort skillval = GetPureSkillValue((SkillType)skillEntry.ParentSkillLineID);
|
||||
SetSkill((SkillType)skillEntry.ParentSkillLineID, (uint)skillEntry.ParentTierIndex, Math.Max(skillval, (ushort)1), tier.Value[skillEntry.ParentTierIndex - 1]);
|
||||
}
|
||||
}
|
||||
if (skillEntry.CategoryID == SkillCategory.Profession)
|
||||
{
|
||||
int freeProfessionSlot = FindProfessionSlotFor(id);
|
||||
if (freeProfessionSlot != -1)
|
||||
SetUInt32Value(ActivePlayerFields.ProfessionSkillLine + freeProfessionSlot, id);
|
||||
}
|
||||
}
|
||||
|
||||
SetUInt16Value(PlayerFields.SkillLineStep + field, offset, (ushort)step);
|
||||
SetUInt16Value(PlayerFields.SkillLineRank + field, offset, (ushort)newVal);
|
||||
SetUInt16Value(PlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineId + field, offset, (ushort)id);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineStep + field, offset, (ushort)step);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineRank + field, offset, (ushort)newVal);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineMaxRank + field, offset, (ushort)maxVal);
|
||||
|
||||
UpdateSkillEnchantments(id, currVal, (ushort)newVal);
|
||||
UpdateCriteria(CriteriaTypes.ReachSkillLevel, id);
|
||||
@@ -1222,8 +1239,8 @@ namespace Game.Entities
|
||||
mSkillStatus.Add(id, new SkillStatusData((uint)i, SkillState.New));
|
||||
|
||||
// apply skill bonuses
|
||||
SetUInt16Value(PlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(PlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLineTempBonus + field, offset, 0);
|
||||
SetUInt16Value(ActivePlayerFields.SkillLinePermBonus + field, offset, 0);
|
||||
|
||||
// temporary bonuses
|
||||
var mModSkill = GetAuraEffectsByType(AuraType.ModSkill);
|
||||
@@ -1264,22 +1281,22 @@ namespace Game.Entities
|
||||
|
||||
foreach (var _spell_idx in bounds)
|
||||
{
|
||||
if (_spell_idx.SkillLine != 0)
|
||||
if (_spell_idx.SkillupSkillLineID != 0)
|
||||
{
|
||||
uint SkillValue = GetPureSkillValue((SkillType)_spell_idx.SkillLine);
|
||||
uint SkillValue = GetPureSkillValue((SkillType)_spell_idx.SkillupSkillLineID);
|
||||
|
||||
// Alchemy Discoveries here
|
||||
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(spellid);
|
||||
if (spellEntry != null && spellEntry.Mechanic == Mechanics.Discovery)
|
||||
{
|
||||
uint discoveredSpell = SkillDiscovery.GetSkillDiscoverySpell(_spell_idx.SkillLine, spellid, this);
|
||||
uint discoveredSpell = SkillDiscovery.GetSkillDiscoverySpell(_spell_idx.SkillupSkillLineID, spellid, this);
|
||||
if (discoveredSpell != 0)
|
||||
LearnSpell(discoveredSpell, false);
|
||||
}
|
||||
|
||||
uint craft_skill_gain = _spell_idx.NumSkillUps * WorldConfig.GetUIntValue(WorldCfg.SkillGainCrafting);
|
||||
|
||||
return UpdateSkillPro(_spell_idx.SkillLine, SkillGainChance(SkillValue, _spell_idx.TrivialSkillLineRankHigh,
|
||||
return UpdateSkillPro(_spell_idx.SkillupSkillLineID, SkillGainChance(SkillValue, _spell_idx.TrivialSkillLineRankHigh,
|
||||
(uint)(_spell_idx.TrivialSkillLineRankHigh + _spell_idx.TrivialSkillLineRankLow) / 2, _spell_idx.TrivialSkillLineRankLow), craft_skill_gain);
|
||||
}
|
||||
}
|
||||
@@ -1299,15 +1316,39 @@ namespace Game.Entities
|
||||
switch (SkillId)
|
||||
{
|
||||
case SkillType.Herbalism:
|
||||
case SkillType.Herbalism2:
|
||||
case SkillType.OutlandHerbalism:
|
||||
case SkillType.NorthrendHerbalism:
|
||||
case SkillType.CataclysmHerbalism:
|
||||
case SkillType.PandariaHerbalism:
|
||||
case SkillType.DraenorHerbalism:
|
||||
case SkillType.LegionHerbalism:
|
||||
case SkillType.KulTiranHerbalism:
|
||||
case SkillType.Jewelcrafting:
|
||||
case SkillType.Inscription:
|
||||
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain);
|
||||
case SkillType.Skinning:
|
||||
case SkillType.Skinning2:
|
||||
case SkillType.OutlandSkinning:
|
||||
case SkillType.NorthrendSkinning:
|
||||
case SkillType.CataclysmSkinning:
|
||||
case SkillType.PandariaSkinning:
|
||||
case SkillType.DraenorSkinning:
|
||||
case SkillType.LegionSkinning:
|
||||
case SkillType.KulTiranSkinning:
|
||||
if (WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps) == 0)
|
||||
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain);
|
||||
else
|
||||
return UpdateSkillPro(SkillId, (int)(SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * Multiplicator) >> (int)(SkillValue / WorldConfig.GetIntValue(WorldCfg.SkillChanceSkinningSteps)), gathering_skill_gain);
|
||||
case SkillType.Mining:
|
||||
case SkillType.Mining2:
|
||||
case SkillType.OutlandMining:
|
||||
case SkillType.NorthrendMining:
|
||||
case SkillType.CataclysmMining:
|
||||
case SkillType.PandariaMining:
|
||||
case SkillType.DraenorMining:
|
||||
case SkillType.LegionMining:
|
||||
case SkillType.KulTiranMining:
|
||||
if (WorldConfig.GetIntValue(WorldCfg.SkillChanceMiningSteps) == 0)
|
||||
return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel + 100, RedLevel + 50, RedLevel + 25) * (int)Multiplicator, gathering_skill_gain);
|
||||
else
|
||||
@@ -1585,9 +1626,11 @@ namespace Game.Entities
|
||||
|
||||
void LearnSkillRewardedSpells(uint skillId, uint skillValue)
|
||||
{
|
||||
long raceMask = getRaceMask();
|
||||
ulong raceMask = getRaceMask();
|
||||
uint classMask = getClassMask();
|
||||
foreach (var ability in CliDB.SkillLineAbilityStorage.Values)
|
||||
|
||||
List<SkillLineAbilityRecord> skillLineAbilities = Global.DB2Mgr.GetSkillLineAbilitiesBySkill(skillId);
|
||||
foreach (var ability in skillLineAbilities)
|
||||
{
|
||||
if (ability.SkillLine != skillId)
|
||||
continue;
|
||||
@@ -1596,11 +1639,11 @@ namespace Game.Entities
|
||||
if (spellInfo == null)
|
||||
continue;
|
||||
|
||||
if (ability.AcquireMethod != AbilytyLearnType.OnSkillValue && ability.AcquireMethod != AbilytyLearnType.OnSkillLearn)
|
||||
if (ability.AcquireMethod != AbilityLearnType.OnSkillValue && ability.AcquireMethod != AbilityLearnType.OnSkillLearn)
|
||||
continue;
|
||||
|
||||
// AcquireMethod == 2 && NumSkillUps == 1 --> automatically learn riding skill spell, else we skip it (client shows riding in spellbook as trainable).
|
||||
if (skillId == (uint)SkillType.Riding && (ability.AcquireMethod != AbilytyLearnType.OnSkillLearn || ability.NumSkillUps != 1))
|
||||
if (skillId == (uint)SkillType.Riding && (ability.AcquireMethod != AbilityLearnType.OnSkillLearn || ability.NumSkillUps != 1))
|
||||
continue;
|
||||
|
||||
// Check race if set
|
||||
@@ -1616,7 +1659,7 @@ namespace Game.Entities
|
||||
continue;
|
||||
|
||||
// need unlearn spell
|
||||
if (skillValue < ability.MinSkillLineRank && ability.AcquireMethod == AbilytyLearnType.OnSkillValue)
|
||||
if (skillValue < ability.MinSkillLineRank && ability.AcquireMethod == AbilityLearnType.OnSkillValue)
|
||||
RemoveSpell(ability.Spell);
|
||||
// need learn
|
||||
else if (!IsInWorld)
|
||||
@@ -1627,6 +1670,49 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
int FindProfessionSlotFor(uint skillId)
|
||||
{
|
||||
SkillLineRecord skillEntry = CliDB.SkillLineStorage.LookupByKey(skillId);
|
||||
if (skillEntry == null)
|
||||
return -1;
|
||||
|
||||
// both free, return first slot
|
||||
if (GetUInt32Value(ActivePlayerFields.ProfessionSkillLine) == 0 && GetUInt32Value(ActivePlayerFields.ProfessionSkillLine + 1) == 0)
|
||||
return 0;
|
||||
|
||||
ActivePlayerFields professionsBegin = ActivePlayerFields.ProfessionSkillLine;
|
||||
ActivePlayerFields professionsEnd = professionsBegin + 2;
|
||||
|
||||
// when any slot is filled we need to check both - one of them might be earlier step of the same profession
|
||||
ActivePlayerFields sameProfessionSlot = professionsEnd;
|
||||
for (var slot = professionsBegin; slot < professionsEnd; ++slot)
|
||||
{
|
||||
SkillLineRecord slotProfession = CliDB.SkillLineStorage.LookupByKey(GetUInt32Value(slot));
|
||||
if (slotProfession != null)
|
||||
{
|
||||
if (slotProfession.ParentSkillLineID == skillEntry.ParentSkillLineID)
|
||||
{
|
||||
sameProfessionSlot = slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sameProfessionSlot != professionsEnd)
|
||||
{
|
||||
if (CliDB.SkillLineStorage.LookupByKey(sameProfessionSlot).ParentTierIndex < skillEntry.ParentTierIndex)
|
||||
return sameProfessionSlot - professionsBegin;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if there is no same profession, find any free slot
|
||||
for (var slot = professionsBegin; slot < professionsEnd; ++slot)
|
||||
if (GetUInt32Value(slot) == 0)
|
||||
return slot - professionsBegin;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RemoveItemDependentAurasAndCasts(Item pItem)
|
||||
{
|
||||
foreach (var pair in GetOwnedAuras())
|
||||
@@ -1920,19 +2006,15 @@ namespace Game.Entities
|
||||
break;
|
||||
case SkillRangeType.Rank:
|
||||
{
|
||||
ushort rank = 1;
|
||||
if (GetClass() == Class.Deathknight && skillId == SkillType.FirstAid)
|
||||
rank = 4;
|
||||
|
||||
SkillTiersEntry tier = Global.ObjectMgr.GetSkillTier(rcInfo.SkillTierID);
|
||||
ushort maxValue = (ushort)tier.Value[Math.Max(rank - 1, 0)];
|
||||
ushort maxValue = (ushort)tier.Value[0];
|
||||
ushort skillValue = 1;
|
||||
if (rcInfo.Flags.HasAnyFlag(SkillRaceClassInfoFlags.AlwaysMaxValue))
|
||||
skillValue = maxValue;
|
||||
else if (GetClass() == Class.Deathknight)
|
||||
skillValue = (ushort)Math.Min(Math.Max(1, (getLevel() - 1) * 5), maxValue);
|
||||
|
||||
SetSkill(skillId, rank, skillValue, maxValue);
|
||||
SetSkill(skillId, 1, skillValue, maxValue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1945,7 +2027,7 @@ namespace Game.Entities
|
||||
SendKnownSpells knownSpells = new SendKnownSpells();
|
||||
knownSpells.InitialLogin = false; // @todo
|
||||
|
||||
foreach (var spell in m_spells)
|
||||
foreach (var spell in m_spells.ToList())
|
||||
{
|
||||
if (spell.Value.State == PlayerSpellState.Removed)
|
||||
continue;
|
||||
@@ -2484,7 +2566,7 @@ namespace Game.Entities
|
||||
continue;
|
||||
|
||||
// Runeforging special case
|
||||
if ((_spell_idx.AcquireMethod == AbilytyLearnType.OnSkillLearn && !HasSkill((SkillType)_spell_idx.SkillLine))
|
||||
if ((_spell_idx.AcquireMethod == AbilityLearnType.OnSkillLearn && !HasSkill((SkillType)_spell_idx.SkillLine))
|
||||
|| ((_spell_idx.SkillLine == (int)SkillType.Runeforging) && _spell_idx.TrivialSkillLineRankHigh == 0))
|
||||
{
|
||||
SkillRaceClassInfoRecord rcInfo = Global.DB2Mgr.GetSkillRaceClassInfo(_spell_idx.SkillLine, GetRace(), GetClass());
|
||||
@@ -3157,10 +3239,10 @@ namespace Game.Entities
|
||||
|
||||
// Check no reagent use mask
|
||||
FlagArray128 noReagentMask = new FlagArray128();
|
||||
noReagentMask[0] = GetUInt32Value(PlayerFields.NoReagentCost1);
|
||||
noReagentMask[1] = GetUInt32Value(PlayerFields.NoReagentCost1 + 1);
|
||||
noReagentMask[2] = GetUInt32Value(PlayerFields.NoReagentCost1 + 2);
|
||||
noReagentMask[3] = GetUInt32Value(PlayerFields.NoReagentCost1 + 3);
|
||||
noReagentMask[0] = GetUInt32Value(ActivePlayerFields.NoReagentCost);
|
||||
noReagentMask[1] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 1);
|
||||
noReagentMask[2] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 2);
|
||||
noReagentMask[3] = GetUInt32Value(ActivePlayerFields.NoReagentCost + 3);
|
||||
if (spellInfo.SpellFamilyFlags & noReagentMask)
|
||||
return true;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Game.Entities
|
||||
if (level < PlayerConst.MinSpecializationLevel)
|
||||
ResetTalentSpecialization();
|
||||
|
||||
uint talentTiers = CalculateTalentsTiers();
|
||||
uint talentTiers = (uint)Global.DB2Mgr.GetNumTalentsAtLevel(level, GetClass());
|
||||
if (level < 15)
|
||||
{
|
||||
// Remove all talent points
|
||||
@@ -50,7 +50,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
SetUInt32Value(PlayerFields.MaxTalentTiers, talentTiers);
|
||||
SetUInt32Value(ActivePlayerFields.MaxTalentTiers, talentTiers);
|
||||
|
||||
if (!GetSession().PlayerLoading())
|
||||
SendTalentsInfoData(); // update at client
|
||||
@@ -127,7 +127,7 @@ namespace Game.Entities
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
// check if we have enough talent points
|
||||
if (talentInfo.TierID >= GetUInt32Value(PlayerFields.MaxTalentTiers))
|
||||
if (talentInfo.TierID >= GetUInt32Value(ActivePlayerFields.MaxTalentTiers))
|
||||
return TalentLearnResult.FailedUnknown;
|
||||
|
||||
// TODO: prevent changing talents that are on cooldown
|
||||
@@ -244,8 +244,8 @@ namespace Game.Entities
|
||||
void SetActiveTalentGroup(byte group) { _specializationInfo.ActiveGroup = group; }
|
||||
|
||||
// Loot Spec
|
||||
public void SetLootSpecId(uint id) { SetUInt32Value(PlayerFields.LootSpecId, id); }
|
||||
uint GetLootSpecId() { return GetUInt32Value(PlayerFields.LootSpecId); }
|
||||
public void SetLootSpecId(uint id) { SetUInt32Value(ActivePlayerFields.LootSpecId, id); }
|
||||
uint GetLootSpecId() { return GetUInt32Value(ActivePlayerFields.LootSpecId); }
|
||||
|
||||
public uint GetDefaultSpecId()
|
||||
{
|
||||
@@ -312,15 +312,6 @@ namespace Game.Entities
|
||||
|
||||
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
|
||||
{
|
||||
// unlearn only talents for character class
|
||||
// some spell learned by one class as normal spells or know at creation but another class learn it as talent,
|
||||
// to prevent unexpected lost normal learned spell skip another class talents
|
||||
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
|
||||
continue;
|
||||
|
||||
if (talentInfo.SpellID == 0)
|
||||
continue;
|
||||
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
|
||||
if (spellInfo == null)
|
||||
continue;
|
||||
@@ -364,17 +355,16 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var talentInfo in CliDB.PvpTalentStorage.Values)
|
||||
for (byte slot = 0; slot < PlayerConst.MaxPvpTalentSlots; ++slot)
|
||||
{
|
||||
// learn only talents for character class (or x-class talents)
|
||||
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
|
||||
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(GetPvpTalentMap(GetActiveTalentGroup())[slot]);
|
||||
if (talentInfo == null)
|
||||
continue;
|
||||
|
||||
if (talentInfo.SpellID == 0)
|
||||
continue;
|
||||
|
||||
if (HasPvpTalent(talentInfo.Id, GetActiveTalentGroup()))
|
||||
AddPvpTalent(talentInfo, GetActiveTalentGroup(), true);
|
||||
AddPvpTalent(talentInfo, GetActiveTalentGroup(), slot);
|
||||
}
|
||||
|
||||
LearnSpecializationSpells();
|
||||
@@ -558,9 +548,6 @@ namespace Game.Entities
|
||||
continue;
|
||||
}
|
||||
|
||||
if (talentInfo.ClassID != (uint)GetClass())
|
||||
continue;
|
||||
|
||||
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
|
||||
if (spellEntry == null)
|
||||
{
|
||||
@@ -571,21 +558,18 @@ namespace Game.Entities
|
||||
groupInfoPkt.TalentIDs.Add((ushort)pair.Key);
|
||||
}
|
||||
|
||||
foreach (var pair in pvpTalents)
|
||||
for (byte slot = 0; slot < PlayerConst.MaxPvpTalentSlots; ++slot)
|
||||
{
|
||||
if (pair.Value == PlayerSpellState.Removed)
|
||||
if (pvpTalents[slot] == 0)
|
||||
continue;
|
||||
|
||||
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(pair.Key);
|
||||
PvpTalentRecord talentInfo = CliDB.PvpTalentStorage.LookupByKey(pvpTalents[slot]);
|
||||
if (talentInfo == null)
|
||||
{
|
||||
Log.outError(LogFilter.Player, $"Player.SendTalentsInfoData: Player '{GetName()}' ({GetGUID().ToString()}) has unknown pvp talent id: {pair.Key}");
|
||||
Log.outError(LogFilter.Player, $"Player.SendTalentsInfoData: Player '{GetName()}' ({GetGUID().ToString()}) has unknown pvp talent id: {pvpTalents[slot]}");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (talentInfo.ClassID != 0 && talentInfo.ClassID != (int)GetClass())
|
||||
continue;
|
||||
|
||||
SpellInfo spellEntry = Global.SpellMgr.GetSpellInfo(talentInfo.SpellID);
|
||||
if (spellEntry == null)
|
||||
{
|
||||
@@ -593,7 +577,7 @@ namespace Game.Entities
|
||||
continue;
|
||||
}
|
||||
|
||||
groupInfoPkt.PvPTalentIDs.Add((ushort)pair.Key);
|
||||
groupInfoPkt.PvPTalentIDs.Add((ushort)pvpTalents[slot]);
|
||||
}
|
||||
|
||||
packet.Info.TalentGroups.Add(groupInfoPkt);
|
||||
@@ -610,28 +594,5 @@ namespace Game.Entities
|
||||
respecWipeConfirm.RespecType = SpecResetType.Talents;
|
||||
SendPacket(respecWipeConfirm);
|
||||
}
|
||||
|
||||
uint CalculateTalentsTiers()
|
||||
{
|
||||
uint[] rowLevels = new uint[0];
|
||||
switch (GetClass())
|
||||
{
|
||||
case Class.Deathknight:
|
||||
rowLevels = new uint[] { 57, 58, 59, 60, 75, 90, 100 };
|
||||
break;
|
||||
case Class.DemonHunter:
|
||||
rowLevels = new uint[] { 99, 100, 102, 104, 106, 108, 110 };
|
||||
break;
|
||||
default:
|
||||
rowLevels = new uint[] { 15, 30, 45, 60, 75, 90, 100 };
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint i = PlayerConst.MaxTalentTiers; i != 0; --i)
|
||||
if (getLevel() >= rowLevels[i - 1])
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ namespace Game.Entities
|
||||
objectTypeMask |= TypeMask.Player;
|
||||
objectTypeId = TypeId.Player;
|
||||
|
||||
valuesCount = (int)PlayerFields.End;
|
||||
_dynamicValuesCount = (int)PlayerDynamicFields.End;
|
||||
valuesCount = (int)ActivePlayerFields.End;
|
||||
_dynamicValuesCount = (int)ActivePlayerDynamicFields.End;
|
||||
Session = session;
|
||||
|
||||
// players always accept
|
||||
@@ -214,7 +214,7 @@ namespace Game.Entities
|
||||
SetFlag(UnitFields.Flags2, UnitFlags2.RegeneratePower);
|
||||
SetFloatValue(UnitFields.HoverHeight, 1.0f); // default for players in 3.0.3
|
||||
|
||||
SetUInt32Value(PlayerFields.WatchedFactionIndex, 0xFFFFFFFF); // -1 is default value
|
||||
SetUInt32Value(ActivePlayerFields.WatchedFactionIndex, 0xFFFFFFFF); // -1 is default value
|
||||
|
||||
SetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetSkinId, createInfo.Skin);
|
||||
SetByteValue(PlayerFields.Bytes, PlayerFieldOffsets.BytesOffsetFaceId, createInfo.Face);
|
||||
@@ -223,23 +223,23 @@ namespace Game.Entities
|
||||
SetByteValue(PlayerFields.Bytes2, PlayerFieldOffsets.Bytes2OffsetFacialStyle, createInfo.FacialHairStyle);
|
||||
for (byte i = 0; i < PlayerConst.CustomDisplaySize; ++i)
|
||||
SetByteValue(PlayerFields.Bytes2, (byte)(PlayerFieldOffsets.Bytes2OffsetCustomDisplayOption + i), createInfo.CustomDisplay[i]);
|
||||
SetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp, (uint)((GetSession().IsARecruiter() || GetSession().GetRecruiterId() != 0) ? PlayerRestState.RAFLinked : PlayerRestState.NotRAFLinked));
|
||||
SetUInt32Value(PlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor, (uint)PlayerRestState.NotRAFLinked);
|
||||
SetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateXp, (uint)((GetSession().IsARecruiter() || GetSession().GetRecruiterId() != 0) ? PlayerRestState.RAFLinked : PlayerRestState.NotRAFLinked));
|
||||
SetUInt32Value(ActivePlayerFields.RestInfo + PlayerFieldOffsets.RestStateHonor, (uint)PlayerRestState.NotRAFLinked);
|
||||
SetByteValue(PlayerFields.Bytes3, PlayerFieldOffsets.Bytes3OffsetGender, (byte)createInfo.Sex);
|
||||
SetByteValue(PlayerFields.Bytes4, PlayerFieldOffsets.Bytes4OffsetArenaFaction, 0);
|
||||
SetInventorySlotCount(InventorySlots.DefaultSize);
|
||||
|
||||
SetGuidValue(ObjectFields.Data, ObjectGuid.Empty);
|
||||
SetGuidValue(UnitFields.GuildGuid, ObjectGuid.Empty);
|
||||
SetUInt32Value(PlayerFields.GuildRank, 0);
|
||||
SetGuildLevel(0);
|
||||
SetUInt32Value(PlayerFields.GuildTimestamp, 0);
|
||||
|
||||
for (int i = 0; i < PlayerConst.KnowTitlesSize; ++i)
|
||||
SetUInt64Value(PlayerFields.KnownTitles + i, 0); // 0=disabled
|
||||
SetUInt64Value(ActivePlayerFields.KnownTitles + i, 0); // 0=disabled
|
||||
SetUInt32Value(PlayerFields.ChosenTitle, 0);
|
||||
|
||||
SetUInt32Value(PlayerFields.Kills, 0);
|
||||
SetUInt32Value(PlayerFields.LifetimeHonorableKills, 0);
|
||||
SetUInt32Value(ActivePlayerFields.Kills, 0);
|
||||
SetUInt32Value(ActivePlayerFields.LifetimeHonorableKills, 0);
|
||||
|
||||
// set starting level
|
||||
uint start_level = WorldConfig.GetUIntValue(WorldCfg.StartPlayerLevel);
|
||||
@@ -274,7 +274,7 @@ namespace Game.Entities
|
||||
|
||||
InitRunes();
|
||||
|
||||
SetUInt64Value(PlayerFields.Coinage, WorldConfig.GetUIntValue(WorldCfg.StartPlayerMoney));
|
||||
SetUInt64Value(ActivePlayerFields.Coinage, WorldConfig.GetUIntValue(WorldCfg.StartPlayerMoney));
|
||||
SetCurrency(CurrencyTypes.ApexisCrystals, WorldConfig.GetUIntValue(WorldCfg.CurrencyStartApexisCrystals));
|
||||
SetCurrency(CurrencyTypes.JusticePoints, WorldConfig.GetUIntValue(WorldCfg.CurrencyStartJusticePoints));
|
||||
|
||||
@@ -282,7 +282,7 @@ namespace Game.Entities
|
||||
if (WorldConfig.GetBoolValue(WorldCfg.StartAllExplored))
|
||||
{
|
||||
for (ushort i = 0; i < PlayerConst.ExploredZonesSize; i++)
|
||||
SetFlag(PlayerFields.ExploredZones1 + i, 0xFFFFFFFF);
|
||||
SetFlag(ActivePlayerFields.ExploredZones + i, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
//Reputations if "StartAllReputation" is enabled, -- TODO: Fix this in a better way
|
||||
@@ -741,6 +741,18 @@ namespace Game.Entities
|
||||
if (pet != null && !pet.IsWithinDistInMap(this, GetMap().GetVisibilityRange()) && !pet.isPossessed())
|
||||
RemovePet(pet, PetSaveMode.NotInSlot, true);
|
||||
|
||||
if (IsAlive())
|
||||
{
|
||||
if (m_hostileReferenceCheckTimer <= diff)
|
||||
{
|
||||
m_hostileReferenceCheckTimer = 15 * Time.InMilliseconds;
|
||||
if (!GetMap().IsDungeon())
|
||||
getHostileRefManager().deleteReferencesOutOfRange(GetVisibilityRange());
|
||||
}
|
||||
else
|
||||
m_hostileReferenceCheckTimer -= diff;
|
||||
}
|
||||
|
||||
//we should execute delayed teleports only for alive(!) players
|
||||
//because we don't want player's ghost teleported from graveyard
|
||||
if (IsHasDelayedTeleport() && IsAlive())
|
||||
@@ -783,7 +795,7 @@ namespace Game.Entities
|
||||
|
||||
if (IsAlive() && !oldIsAlive)
|
||||
//clear aura case after resurrection by another way (spells will be applied before next death)
|
||||
ClearDynamicValue(PlayerDynamicFields.SelfResSpells);
|
||||
ClearDynamicValue(ActivePlayerDynamicFields.SelfResSpells);
|
||||
}
|
||||
|
||||
public override void DestroyForPlayer(Player target)
|
||||
@@ -1662,15 +1674,15 @@ namespace Game.Entities
|
||||
continue;
|
||||
|
||||
if (quest.IsDaily())
|
||||
rep = CalculateReputationGain(ReputationSource.DailyQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
rep = CalculateReputationGain(ReputationSource.DailyQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
else if (quest.IsWeekly())
|
||||
rep = CalculateReputationGain(ReputationSource.WeeklyQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
rep = CalculateReputationGain(ReputationSource.WeeklyQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
else if (quest.IsMonthly())
|
||||
rep = CalculateReputationGain(ReputationSource.MonthlyQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
rep = CalculateReputationGain(ReputationSource.MonthlyQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
else if (quest.IsRepeatable())
|
||||
rep = CalculateReputationGain(ReputationSource.RepeatableQuest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
rep = CalculateReputationGain(ReputationSource.RepeatableQuest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
else
|
||||
rep = CalculateReputationGain(ReputationSource.Quest, GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
rep = CalculateReputationGain(ReputationSource.Quest, (uint)GetQuestLevel(quest), rep, (int)quest.RewardFactionId[i], noQuestBonus);
|
||||
|
||||
bool noSpillover = Convert.ToBoolean(quest.RewardReputationMask & (1 << i));
|
||||
GetReputationMgr().ModifyReputation(factionEntry, rep, noSpillover);
|
||||
@@ -4180,7 +4192,7 @@ namespace Game.Entities
|
||||
if (m_unitMovedByMe == obj)
|
||||
return true;
|
||||
|
||||
ObjectGuid guid = GetGuidValue(PlayerFields.Farsight);
|
||||
ObjectGuid guid = GetGuidValue(ActivePlayerFields.Farsight);
|
||||
if (!guid.IsEmpty())
|
||||
if (obj.GetGUID() == guid)
|
||||
return true;
|
||||
@@ -4542,7 +4554,7 @@ namespace Game.Entities
|
||||
setDeathState(DeathState.Corpse);
|
||||
|
||||
SetUInt32Value(ObjectFields.DynamicFlags, 0);
|
||||
ApplyModFlag(PlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(GetMapId()).Instanceable() && !HasAuraType(AuraType.PreventResurrection));
|
||||
ApplyModFlag(ActivePlayerFields.LocalFlags, PlayerLocalFlags.ReleaseTimer, !CliDB.MapStorage.LookupByKey(GetMapId()).Instanceable() && !HasAuraType(AuraType.PreventResurrection));
|
||||
|
||||
// 6 minutes until repop at graveyard
|
||||
m_deathTimer = 6 * Time.Minute * Time.InMilliseconds;
|
||||
@@ -5009,6 +5021,7 @@ namespace Game.Entities
|
||||
|
||||
displayPlayerChoice.CloseChoiceFrame = false;
|
||||
displayPlayerChoice.HideWarboardHeader = playerChoice.HideWarboardHeader;
|
||||
displayPlayerChoice.KeepOpenAfterChoice = playerChoice.KeepOpenAfterChoice;
|
||||
|
||||
for (var i = 0; i < playerChoice.Responses.Count; ++i)
|
||||
{
|
||||
@@ -5017,6 +5030,9 @@ namespace Game.Entities
|
||||
|
||||
playerChoiceResponse.ResponseID = playerChoiceResponseTemplate.ResponseId;
|
||||
playerChoiceResponse.ChoiceArtFileID = playerChoiceResponseTemplate.ChoiceArtFileId;
|
||||
playerChoiceResponse.Flags = playerChoiceResponseTemplate.Flags;
|
||||
playerChoiceResponse.WidgetSetID = playerChoiceResponseTemplate.WidgetSetID;
|
||||
playerChoiceResponse.GroupID = playerChoiceResponseTemplate.GroupID;
|
||||
playerChoiceResponse.Answer = playerChoiceResponseTemplate.Answer;
|
||||
playerChoiceResponse.Header = playerChoiceResponseTemplate.Header;
|
||||
playerChoiceResponse.Description = playerChoiceResponseTemplate.Description;
|
||||
@@ -5173,7 +5189,7 @@ namespace Game.Entities
|
||||
public int GetTeamId() { return m_team == Team.Alliance ? TeamId.Alliance : TeamId.Horde; }
|
||||
|
||||
//Money
|
||||
public ulong GetMoney() { return GetUInt64Value(PlayerFields.Coinage); }
|
||||
public ulong GetMoney() { return GetUInt64Value(ActivePlayerFields.Coinage); }
|
||||
public bool HasEnoughMoney(ulong amount) { return GetMoney() >= amount; }
|
||||
public bool HasEnoughMoney(long amount)
|
||||
{
|
||||
@@ -5205,7 +5221,7 @@ namespace Game.Entities
|
||||
}
|
||||
public void SetMoney(ulong value)
|
||||
{
|
||||
SetUInt64Value(PlayerFields.Coinage, value);
|
||||
SetUInt64Value(ActivePlayerFields.Coinage, value);
|
||||
MoneyChanged((uint)value);
|
||||
UpdateCriteria(CriteriaTypes.HighestGoldValueOwned);
|
||||
}
|
||||
@@ -5246,19 +5262,18 @@ namespace Game.Entities
|
||||
public void SetInGuild(ulong guildId)
|
||||
{
|
||||
if (guildId != 0)
|
||||
SetGuidValue(ObjectFields.Data, ObjectGuid.Create(HighGuid.Guild, guildId));
|
||||
SetGuidValue(UnitFields.GuildGuid, ObjectGuid.Create(HighGuid.Guild, guildId));
|
||||
else
|
||||
SetGuidValue(ObjectFields.Data, ObjectGuid.Empty);
|
||||
SetGuidValue(UnitFields.GuildGuid, ObjectGuid.Empty);
|
||||
|
||||
ApplyModFlag(PlayerFields.Flags, PlayerFlags.GuildLevelEnabled, guildId != 0);
|
||||
SetUInt16Value(ObjectFields.Type, 1, (ushort)(guildId != 0 ? 1 : 0));
|
||||
}
|
||||
public void SetGuildRank(uint rankId) { SetUInt32Value(PlayerFields.GuildRank, rankId); }
|
||||
byte GetGuildRank() { return (byte)GetUInt32Value(PlayerFields.GuildRank); }
|
||||
public void SetGuildLevel(uint level) { SetUInt32Value(PlayerFields.GuildLevel, level); }
|
||||
uint GetGuildLevel() { return GetUInt32Value(PlayerFields.GuildLevel); }
|
||||
public void SetGuildIdInvited(ulong GuildId) { m_GuildIdInvited = GuildId; }
|
||||
public uint GetGuildId() { return GetUInt32Value(ObjectFields.Data); }
|
||||
public uint GetGuildId() { return GetUInt32Value(UnitFields.GuildGuid); }
|
||||
public Guild GetGuild()
|
||||
{
|
||||
uint guildId = GetGuildId();
|
||||
@@ -5270,7 +5285,7 @@ namespace Game.Entities
|
||||
return GetGuildId() != 0 ? Global.GuildMgr.GetGuildById(GetGuildId()).GetName() : "";
|
||||
}
|
||||
|
||||
public void SetFreePrimaryProfessions(uint profs) { SetUInt32Value(PlayerFields.CharacterPoints, profs); }
|
||||
public void SetFreePrimaryProfessions(uint profs) { SetUInt32Value(ActivePlayerFields.CharacterPoints, profs); }
|
||||
public void GiveLevel(uint level)
|
||||
{
|
||||
var oldLevel = getLevel();
|
||||
@@ -5301,13 +5316,12 @@ namespace Game.Entities
|
||||
for (Stats i = Stats.Strength; i < Stats.Max; ++i)
|
||||
packet.StatDelta[(int)i] = info.stats[(int)i] - (int)GetCreateStat(i);
|
||||
|
||||
uint[] rowLevels = (GetClass() != Class.Deathknight) ? PlayerConst.DefaultTalentRowLevels : PlayerConst.DKTalentRowLevels;
|
||||
|
||||
packet.Cp = rowLevels.Any(p => p == level) ? 1 : 0;
|
||||
packet.NumNewTalents = (int)(Global.DB2Mgr.GetNumTalentsAtLevel(level, GetClass()) - Global.DB2Mgr.GetNumTalentsAtLevel(oldLevel, GetClass()));
|
||||
packet.NumNewPvpTalentSlots = Global.DB2Mgr.GetPvpTalentNumSlotsAtLevel(level, GetClass()) - Global.DB2Mgr.GetPvpTalentNumSlotsAtLevel(oldLevel, GetClass());
|
||||
|
||||
SendPacket(packet);
|
||||
|
||||
SetUInt32Value(PlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(level));
|
||||
SetUInt32Value(ActivePlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(level));
|
||||
|
||||
//update level, max level of skills
|
||||
m_PlayedTimeLevel = 0; // Level Played Time reset
|
||||
@@ -5377,8 +5391,8 @@ namespace Game.Entities
|
||||
{
|
||||
++m_grantableLevels;
|
||||
|
||||
if (!HasByteFlag(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01))
|
||||
SetByteFlag(PlayerFields.FieldBytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
|
||||
if (!HasByteFlag(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01))
|
||||
SetByteFlag(ActivePlayerFields.Bytes, PlayerFieldOffsets.FieldBytesOffsetRafGrantableLevel, 0x01);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5449,6 +5463,8 @@ namespace Game.Entities
|
||||
Log.outError(LogFilter.Player, "Player {0} ({1}) has invalid gender {2}", GetName(), GetGUID().ToString(), gender);
|
||||
return;
|
||||
}
|
||||
|
||||
SetUInt32Value(UnitFields.StateAnimId, (uint)CliDB.AnimationDataStorage.Count);
|
||||
}
|
||||
|
||||
//Creature
|
||||
@@ -5782,8 +5798,8 @@ namespace Game.Entities
|
||||
|
||||
PlayerLevelInfo info = Global.ObjectMgr.GetPlayerLevelInfo(GetRace(), GetClass(), getLevel());
|
||||
|
||||
SetUInt32Value(PlayerFields.MaxLevel, WorldConfig.GetUIntValue(WorldCfg.MaxPlayerLevel));
|
||||
SetUInt32Value(PlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(getLevel()));
|
||||
SetUInt32Value(ActivePlayerFields.MaxLevel, WorldConfig.GetUIntValue(WorldCfg.MaxPlayerLevel));
|
||||
SetUInt32Value(ActivePlayerFields.NextLevelXp, Global.ObjectMgr.GetXPForLevel(getLevel()));
|
||||
|
||||
// reset before any aura state sources (health set/aura apply)
|
||||
SetUInt32Value(UnitFields.AuraState, 0);
|
||||
@@ -5813,26 +5829,26 @@ namespace Game.Entities
|
||||
//set create powers
|
||||
SetCreateMana(basemana);
|
||||
|
||||
SetArmor((int)(GetCreateStat(Stats.Agility) * 2));
|
||||
SetArmor((int)(GetCreateStat(Stats.Agility) * 2), 0);
|
||||
|
||||
InitStatBuffMods();
|
||||
|
||||
//reset rating fields values
|
||||
for (var index = PlayerFields.CombatRating1; index < PlayerFields.CombatRating1 + (int)CombatRating.Max; ++index)
|
||||
SetUInt32Value(index, 0);
|
||||
for (var index = 0; index < (int)CombatRating.Max; ++index)
|
||||
SetUInt32Value(ActivePlayerFields.CombatRating + index, 0);
|
||||
|
||||
SetUInt32Value(PlayerFields.ModHealingDonePos, 0);
|
||||
SetFloatValue(PlayerFields.ModHealingPct, 1.0f);
|
||||
SetFloatValue(PlayerFields.ModHealingDonePct, 1.0f);
|
||||
SetFloatValue(PlayerFields.ModPeriodicHealingDonePercent, 1.0f);
|
||||
SetUInt32Value(ActivePlayerFields.ModHealingDonePos, 0);
|
||||
SetFloatValue(ActivePlayerFields.ModHealingPct, 1.0f);
|
||||
SetFloatValue(ActivePlayerFields.ModHealingDonePct, 1.0f);
|
||||
SetFloatValue(ActivePlayerFields.ModPeriodicHealingDonePercent, 1.0f);
|
||||
for (byte i = 0; i < 7; ++i)
|
||||
{
|
||||
SetInt32Value(PlayerFields.ModDamageDoneNeg + i, 0);
|
||||
SetInt32Value(PlayerFields.ModDamageDonePos + i, 0);
|
||||
SetFloatValue(PlayerFields.ModDamageDonePct + i, 1.0f);
|
||||
SetInt32Value(ActivePlayerFields.ModDamageDoneNeg + i, 0);
|
||||
SetInt32Value(ActivePlayerFields.ModDamageDonePos + i, 0);
|
||||
SetFloatValue(ActivePlayerFields.ModDamageDonePct + i, 1.0f);
|
||||
}
|
||||
|
||||
SetFloatValue(PlayerFields.ModSpellPowerPct, 1.0f);
|
||||
SetFloatValue(ActivePlayerFields.ModSpellPowerPct, 1.0f);
|
||||
|
||||
//reset attack power, damage and attack speed fields
|
||||
for (byte i = 0; i < (int)WeaponAttackType.Max; ++i)
|
||||
@@ -5846,8 +5862,8 @@ namespace Game.Entities
|
||||
SetFloatValue(UnitFields.MaxRangedDamage, 0.0f);
|
||||
for (var i = 0; i < 3; ++i)
|
||||
{
|
||||
SetFloatValue(PlayerFields.WeaponDmgMultipliers + i, 1.0f);
|
||||
SetFloatValue(PlayerFields.WeaponAtkSpeedMultipliers + i, 1.0f);
|
||||
SetFloatValue(ActivePlayerFields.WeaponDmgMultipliers + i, 1.0f);
|
||||
SetFloatValue(ActivePlayerFields.WeaponAtkSpeedMultipliers + i, 1.0f);
|
||||
}
|
||||
|
||||
SetInt32Value(UnitFields.AttackPower, 0);
|
||||
@@ -5856,44 +5872,42 @@ namespace Game.Entities
|
||||
SetFloatValue(UnitFields.RangedAttackPowerMultiplier, 0.0f);
|
||||
|
||||
// Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset
|
||||
SetFloatValue(PlayerFields.CritPercentage, 0.0f);
|
||||
SetFloatValue(PlayerFields.OffhandCritPercentage, 0.0f);
|
||||
SetFloatValue(PlayerFields.RangedCritPercentage, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.CritPercentage, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.OffhandCritPercentage, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.RangedCritPercentage, 0.0f);
|
||||
|
||||
// Init spell schools (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset
|
||||
SetFloatValue(PlayerFields.SpellCritPercentage1, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.SpellCritPercentage1, 0.0f);
|
||||
|
||||
SetFloatValue(PlayerFields.ParryPercentage, 0.0f);
|
||||
SetFloatValue(PlayerFields.BlockPercentage, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.ParryPercentage, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.BlockPercentage, 0.0f);
|
||||
|
||||
// Static 30% damage blocked
|
||||
SetUInt32Value(PlayerFields.ShieldBlock, 30);
|
||||
SetUInt32Value(ActivePlayerFields.ShieldBlock, 30);
|
||||
|
||||
// Dodge percentage
|
||||
SetFloatValue(PlayerFields.DodgePercentage, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.DodgePercentage, 0.0f);
|
||||
|
||||
// set armor (resistance 0) to original value (create_agility*2)
|
||||
SetArmor((int)(GetCreateStat(Stats.Agility) * 2));
|
||||
SetResistanceBuffMods(SpellSchools.Normal, true, 0.0f);
|
||||
SetResistanceBuffMods(SpellSchools.Normal, false, 0.0f);
|
||||
SetArmor((int)(GetCreateStat(Stats.Agility) * 2), 0);
|
||||
SetBonusResistanceMod(SpellSchools.Normal, 0);
|
||||
// set other resistance to original value (0)
|
||||
for (var spellSchool = SpellSchools.Holy; spellSchool < SpellSchools.Max; ++spellSchool)
|
||||
{
|
||||
SetResistance(spellSchool, 0);
|
||||
SetResistanceBuffMods(spellSchool, true, 0.0f);
|
||||
SetResistanceBuffMods(spellSchool, false, 0.0f);
|
||||
SetBonusResistanceMod(spellSchool, 0);
|
||||
}
|
||||
|
||||
SetUInt32Value(PlayerFields.ModTargetResistance, 0);
|
||||
SetUInt32Value(PlayerFields.ModTargetPhysicalResistance, 0);
|
||||
SetUInt32Value(ActivePlayerFields.ModTargetResistance, 0);
|
||||
SetUInt32Value(ActivePlayerFields.ModTargetPhysicalResistance, 0);
|
||||
for (var i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
{
|
||||
SetUInt32Value(UnitFields.PowerCostModifier + i, 0);
|
||||
SetFloatValue(UnitFields.PowerCostMultiplier + i, 0.0f);
|
||||
}
|
||||
// Reset no reagent cost field
|
||||
for (byte i = 0; i < 3; ++i)
|
||||
SetUInt32Value(PlayerFields.NoReagentCost1 + i, 0);
|
||||
for (byte i = 0; i < 4; ++i)
|
||||
SetUInt32Value(ActivePlayerFields.NoReagentCost + i, 0);
|
||||
// Init data for form but skip reapply item mods for form
|
||||
InitDataForForm(reapplyMods);
|
||||
|
||||
@@ -5925,9 +5939,9 @@ namespace Game.Entities
|
||||
RemoveByteFlag(UnitFields.Bytes2, UnitBytes2Offsets.PvpFlag, (UnitBytes2Flags.FFAPvp | UnitBytes2Flags.Sanctuary));
|
||||
|
||||
// restore if need some important flags
|
||||
SetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetIgnorePowerRegenPredictionMask, 0);
|
||||
SetByteValue(PlayerFields.FieldBytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, 0);
|
||||
SetByteValue(PlayerFields.FieldBytes2, 3, 0);
|
||||
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetIgnorePowerRegenPredictionMask, 0);
|
||||
SetByteValue(ActivePlayerFields.Bytes2, PlayerFieldOffsets.FieldBytes2OffsetAuraVision, 0);
|
||||
SetByteValue(ActivePlayerFields.Bytes2, 3, 0);
|
||||
|
||||
if (reapplyMods) // reapply stats values only on .reset stats (level) command
|
||||
_ApplyAllStatBonuses();
|
||||
@@ -6258,11 +6272,11 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
uint val = 1u << (areaEntry.AreaBit % 32);
|
||||
uint currFields = GetUInt32Value(PlayerFields.ExploredZones1 + offset);
|
||||
uint currFields = GetUInt32Value(ActivePlayerFields.ExploredZones + offset);
|
||||
|
||||
if (!Convert.ToBoolean(currFields & val))
|
||||
{
|
||||
SetUInt32Value(PlayerFields.ExploredZones1 + offset, currFields | val);
|
||||
SetUInt32Value(ActivePlayerFields.ExploredZones + offset, currFields | val);
|
||||
|
||||
UpdateCriteria(CriteriaTypes.ExploreArea);
|
||||
|
||||
@@ -6488,15 +6502,15 @@ namespace Game.Entities
|
||||
|
||||
void SetXP(uint xp)
|
||||
{
|
||||
SetUInt32Value(PlayerFields.Xp, xp);
|
||||
SetUInt32Value(ActivePlayerFields.Xp, xp);
|
||||
|
||||
int playerLevelDelta = 0;
|
||||
|
||||
// If XP < 50%, player should see scaling creature with -1 level except for level max
|
||||
if (getLevel() < SharedConst.MaxLevel && xp < (GetUInt32Value(PlayerFields.NextLevelXp) / 2))
|
||||
if (getLevel() < SharedConst.MaxLevel && xp < (GetUInt32Value(ActivePlayerFields.NextLevelXp) / 2))
|
||||
playerLevelDelta = -1;
|
||||
|
||||
SetInt32Value(PlayerFields.ScalingLevelDelta, playerLevelDelta);
|
||||
SetInt32Value(UnitFields.ScalingLevelDelta, playerLevelDelta);
|
||||
}
|
||||
|
||||
public void GiveXP(uint xp, Unit victim, float group_rate = 1.0f)
|
||||
@@ -6539,8 +6553,8 @@ namespace Game.Entities
|
||||
packet.ReferAFriendBonusType = (byte)(recruitAFriend ? 1 : 0);
|
||||
SendPacket(packet);
|
||||
|
||||
uint curXP = GetUInt32Value(PlayerFields.Xp);
|
||||
uint nextLvlXP = GetUInt32Value(PlayerFields.NextLevelXp);
|
||||
uint curXP = GetUInt32Value(ActivePlayerFields.Xp);
|
||||
uint nextLvlXP = GetUInt32Value(ActivePlayerFields.NextLevelXp);
|
||||
uint newXP = curXP + xp + bonus_xp;
|
||||
|
||||
while (newXP >= nextLvlXP && level < WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel))
|
||||
@@ -6551,7 +6565,7 @@ namespace Game.Entities
|
||||
GiveLevel(level + 1);
|
||||
|
||||
level = getLevel();
|
||||
nextLvlXP = GetUInt32Value(PlayerFields.NextLevelXp);
|
||||
nextLvlXP = GetUInt32Value(ActivePlayerFields.NextLevelXp);
|
||||
}
|
||||
|
||||
SetXP(newXP);
|
||||
@@ -6758,22 +6772,6 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
// check node starting pos data set case if provided
|
||||
if (node.Pos.X != 0.0f || node.Pos.Y != 0.0f || node.Pos.Z != 0.0f)
|
||||
{
|
||||
if (node.ContinentID != GetMapId() || !IsInDist(node.Pos.X, node.Pos.Y, node.Pos.Z, 2 * SharedConst.InteractionDistance))
|
||||
{
|
||||
GetSession().SendActivateTaxiReply(ActivateTaxiReply.TooFarAway);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// node must have pos if taxi master case (npc != NULL)
|
||||
else if (npc != null)
|
||||
{
|
||||
GetSession().SendActivateTaxiReply(ActivateTaxiReply.UnspecifiedServerError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepare to flight start now
|
||||
|
||||
// stop combat at start taxi flight if any
|
||||
@@ -7084,7 +7082,7 @@ namespace Game.Entities
|
||||
}
|
||||
public bool IsSpellFitByClassAndRace(uint spell_id)
|
||||
{
|
||||
long racemask = getRaceMask();
|
||||
ulong racemask = getRaceMask();
|
||||
uint classmask = getClassMask();
|
||||
|
||||
var bounds = Global.SpellMgr.GetSkillLineAbilityMapBounds(spell_id);
|
||||
@@ -7113,8 +7111,8 @@ namespace Game.Entities
|
||||
{
|
||||
SetFreePrimaryProfessions(WorldConfig.GetUIntValue(WorldCfg.MaxPrimaryTradeSkill));
|
||||
}
|
||||
public uint GetFreePrimaryProfessionPoints() { return GetUInt32Value(PlayerFields.CharacterPoints); }
|
||||
void SetFreePrimaryProfessions(ushort profs) { SetUInt32Value(PlayerFields.CharacterPoints, profs); }
|
||||
public uint GetFreePrimaryProfessionPoints() { return GetUInt32Value(ActivePlayerFields.CharacterPoints); }
|
||||
void SetFreePrimaryProfessions(ushort profs) { SetUInt32Value(ActivePlayerFields.CharacterPoints, profs); }
|
||||
public bool HaveAtClient(WorldObject u)
|
||||
{
|
||||
bool one = u.GetGUID() == GetGUID();
|
||||
@@ -7130,7 +7128,7 @@ namespace Game.Entities
|
||||
|
||||
int fieldIndexOffset = (int)bitIndex / 32;
|
||||
uint flag = (uint)(1 << ((int)bitIndex % 32));
|
||||
return HasFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag);
|
||||
return HasFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag);
|
||||
}
|
||||
public void SetTitle(CharTitlesRecord title, bool lost = false)
|
||||
{
|
||||
@@ -7139,17 +7137,17 @@ namespace Game.Entities
|
||||
|
||||
if (lost)
|
||||
{
|
||||
if (!HasFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag))
|
||||
if (!HasFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag))
|
||||
return;
|
||||
|
||||
RemoveFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag);
|
||||
RemoveFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HasFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag))
|
||||
if (HasFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag))
|
||||
return;
|
||||
|
||||
SetFlag(PlayerFields.KnownTitles + fieldIndexOffset, flag);
|
||||
SetFlag(ActivePlayerFields.KnownTitles + fieldIndexOffset, flag);
|
||||
}
|
||||
|
||||
TitleEarned packet = new TitleEarned(lost ? ServerOpcodes.TitleLost : ServerOpcodes.TitleEarned);
|
||||
@@ -7163,7 +7161,7 @@ namespace Game.Entities
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "Player.CreateViewpoint: Player {0} create seer {1} (TypeId: {2}).", GetName(), target.GetEntry(), target.GetTypeId());
|
||||
|
||||
if (!AddGuidValue(PlayerFields.Farsight, target.GetGUID()))
|
||||
if (!AddGuidValue(ActivePlayerFields.Farsight, target.GetGUID()))
|
||||
{
|
||||
Log.outFatal(LogFilter.Player, "Player.CreateViewpoint: Player {0} cannot add new viewpoint!", GetName());
|
||||
return;
|
||||
@@ -7181,7 +7179,7 @@ namespace Game.Entities
|
||||
{
|
||||
Log.outDebug(LogFilter.Maps, "Player.CreateViewpoint: Player {0} remove seer", GetName());
|
||||
|
||||
if (!RemoveGuidValue(PlayerFields.Farsight, target.GetGUID()))
|
||||
if (!RemoveGuidValue(ActivePlayerFields.Farsight, target.GetGUID()))
|
||||
{
|
||||
Log.outFatal(LogFilter.Player, "Player.CreateViewpoint: Player {0} cannot remove current viewpoint!", GetName());
|
||||
return;
|
||||
@@ -7196,7 +7194,7 @@ namespace Game.Entities
|
||||
}
|
||||
public WorldObject GetViewpoint()
|
||||
{
|
||||
ObjectGuid guid = GetGuidValue(PlayerFields.Farsight);
|
||||
ObjectGuid guid = GetGuidValue(ActivePlayerFields.Farsight);
|
||||
if (!guid.IsEmpty())
|
||||
return Global.ObjAccessor.GetObjectByTypeMask(this, guid, TypeMask.Seer);
|
||||
return null;
|
||||
|
||||
@@ -225,13 +225,13 @@ namespace Game.Entities
|
||||
|
||||
public bool IsTaximaskNodeKnown(uint nodeidx)
|
||||
{
|
||||
byte field = (byte)((nodeidx - 1) / 8);
|
||||
uint field = (nodeidx - 1) / 8;
|
||||
uint submask = (uint)(1 << (int)((nodeidx - 1) % 8));
|
||||
return (m_taximask[field] & submask) == submask;
|
||||
}
|
||||
public bool SetTaximaskNode(uint nodeidx)
|
||||
{
|
||||
byte field = (byte)((nodeidx - 1) / 8);
|
||||
uint field = (nodeidx - 1) / 8;
|
||||
uint submask = (uint)(1 << (int)((nodeidx - 1) % 8));
|
||||
if ((m_taximask[field] & submask) != submask)
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Game.Entities
|
||||
{
|
||||
byte rest_rested_offset;
|
||||
byte rest_state_offset;
|
||||
PlayerFields next_level_xp_field;
|
||||
ActivePlayerFields next_level_xp_field;
|
||||
bool affectedByRaF = false;
|
||||
|
||||
switch (restType)
|
||||
@@ -25,17 +25,17 @@ namespace Game.Entities
|
||||
|
||||
rest_rested_offset = PlayerFieldOffsets.RestRestedXp;
|
||||
rest_state_offset = PlayerFieldOffsets.RestStateXp;
|
||||
next_level_xp_field = PlayerFields.NextLevelXp;
|
||||
next_level_xp_field = ActivePlayerFields.NextLevelXp;
|
||||
affectedByRaF = true;
|
||||
break;
|
||||
case RestTypes.Honor:
|
||||
// Reset restBonus (Honor only) for players with max honor level.
|
||||
if (_player.IsMaxHonorLevelAndPrestige())
|
||||
if (_player.IsMaxHonorLevel())
|
||||
restBonus = 0;
|
||||
|
||||
rest_rested_offset = PlayerFieldOffsets.RestRestedHonor;
|
||||
rest_state_offset = PlayerFieldOffsets.RestStateHonor;
|
||||
next_level_xp_field = PlayerFields.HonorNextLevel;
|
||||
next_level_xp_field = ActivePlayerFields.HonorNextLevel;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -53,17 +53,17 @@ namespace Game.Entities
|
||||
|
||||
// update data for client
|
||||
if (affectedByRaF && _player.GetsRecruitAFriendBonus(true) && (_player.GetSession().IsARecruiter() || _player.GetSession().GetRecruiterId() != 0))
|
||||
_player.SetUInt32Value(PlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.RAFLinked);
|
||||
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.RAFLinked);
|
||||
else
|
||||
{
|
||||
if (_restBonus[(int)restType] > 10)
|
||||
_player.SetUInt32Value(PlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.Rested);
|
||||
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.Rested);
|
||||
else if (_restBonus[(int)restType] <= 1)
|
||||
_player.SetUInt32Value(PlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.NotRAFLinked);
|
||||
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_state_offset, (uint)PlayerRestState.NotRAFLinked);
|
||||
}
|
||||
|
||||
// RestTickUpdate
|
||||
_player.SetUInt32Value(PlayerFields.RestInfo + rest_rested_offset, (uint)_restBonus[(int)restType]);
|
||||
_player.SetUInt32Value(ActivePlayerFields.RestInfo + rest_rested_offset, (uint)_restBonus[(int)restType]);
|
||||
}
|
||||
|
||||
public void AddRestBonus(RestTypes restType, float restBonus)
|
||||
@@ -135,8 +135,8 @@ namespace Game.Entities
|
||||
public void LoadRestBonus(RestTypes restType, PlayerRestState state, float restBonus)
|
||||
{
|
||||
_restBonus[(int)restType] = restBonus;
|
||||
_player.SetUInt32Value(PlayerFields.RestInfo + (int)restType * 2, (uint)state);
|
||||
_player.SetUInt32Value(PlayerFields.RestInfo + (int)restType * 2 + 1, (uint)restBonus);
|
||||
_player.SetUInt32Value(ActivePlayerFields.RestInfo + (int)restType * 2, (uint)state);
|
||||
_player.SetUInt32Value(ActivePlayerFields.RestInfo + (int)restType * 2 + 1, (uint)restBonus);
|
||||
}
|
||||
|
||||
public float CalcExtraPerSec(RestTypes restType, float bubble)
|
||||
@@ -144,9 +144,9 @@ namespace Game.Entities
|
||||
switch (restType)
|
||||
{
|
||||
case RestTypes.Honor:
|
||||
return (_player.GetUInt32Value(PlayerFields.HonorNextLevel)) / 72000.0f * bubble;
|
||||
return (_player.GetUInt32Value(ActivePlayerFields.HonorNextLevel)) / 72000.0f * bubble;
|
||||
case RestTypes.XP:
|
||||
return (_player.GetUInt32Value(PlayerFields.NextLevelXp)) / 72000.0f * bubble;
|
||||
return (_player.GetUInt32Value(ActivePlayerFields.NextLevelXp)) / 72000.0f * bubble;
|
||||
default:
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,17 @@ namespace Game.Entities
|
||||
|
||||
public virtual bool UpdateStats(Stats stat) { return false; }
|
||||
public virtual bool UpdateAllStats() { return false; }
|
||||
public virtual void UpdateResistances(SpellSchools school) { }
|
||||
public virtual void UpdateResistances(SpellSchools school)
|
||||
{
|
||||
if (school > SpellSchools.Normal)
|
||||
{
|
||||
UnitMods unitMod = UnitMods.ResistanceStart + (int)school;
|
||||
SetResistance(school, (int)m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BaseValue]);
|
||||
SetBonusResistanceMod(school, (int)(GetTotalAuraModValue(unitMod) - GetResistance(school)));
|
||||
}
|
||||
else
|
||||
UpdateArmor();
|
||||
}
|
||||
public virtual void UpdateArmor() { }
|
||||
public virtual void UpdateMaxHealth() { }
|
||||
public virtual void UpdateMaxPower(PowerType power) { }
|
||||
@@ -257,30 +267,43 @@ namespace Game.Entities
|
||||
}
|
||||
public uint GetArmor()
|
||||
{
|
||||
return GetResistance(SpellSchools.Normal);
|
||||
return (uint)(GetResistance(SpellSchools.Normal) + GetBonusResistanceMod(SpellSchools.Normal));
|
||||
}
|
||||
public void SetArmor(int val)
|
||||
public void SetArmor(int val, int bonusVal)
|
||||
{
|
||||
SetResistance(SpellSchools.Normal, val);
|
||||
SetBonusResistanceMod(SpellSchools.Normal, bonusVal);
|
||||
}
|
||||
public uint GetResistance(SpellSchools school)
|
||||
public int GetResistance(SpellSchools school)
|
||||
{
|
||||
return GetUInt32Value(UnitFields.Resistances + (int)school);
|
||||
return GetInt32Value(UnitFields.Resistances + (int)school);
|
||||
}
|
||||
public uint GetResistance(SpellSchoolMask mask)
|
||||
public int GetBonusResistanceMod(SpellSchools school)
|
||||
{
|
||||
int resist = -1;
|
||||
return GetInt32Value(UnitFields.BonusResistanceMods + (int)school);
|
||||
}
|
||||
public int GetResistance(SpellSchoolMask mask)
|
||||
{
|
||||
int? resist = null;
|
||||
for (int i = (int)SpellSchools.Normal; i < (int)SpellSchools.Max; ++i)
|
||||
if (Convert.ToBoolean((int)mask & (1 << i)) && (resist < 0 || resist > GetResistance((SpellSchools)i)))
|
||||
resist = (int)GetResistance((SpellSchools)i);
|
||||
{
|
||||
int schoolResistance = GetResistance((SpellSchools)i) + GetBonusResistanceMod((SpellSchools)i);
|
||||
if (Convert.ToBoolean((int)mask & (1 << i)) && (!resist.HasValue || resist.Value > schoolResistance))
|
||||
resist = schoolResistance;
|
||||
}
|
||||
|
||||
// resist value will never be negative here
|
||||
return (uint)resist;
|
||||
return resist.HasValue ? resist.Value : 0;
|
||||
}
|
||||
public void SetResistance(SpellSchools school, int val)
|
||||
{
|
||||
SetStatInt32Value(UnitFields.Resistances + (int)school, val);
|
||||
}
|
||||
public void SetBonusResistanceMod(SpellSchools school, int val)
|
||||
{
|
||||
SetStatInt32Value(UnitFields.BonusResistanceMods + (int)school, val);
|
||||
}
|
||||
|
||||
public float GetCreateStat(Stats stat)
|
||||
{
|
||||
return CreateStats[(int)stat];
|
||||
@@ -293,23 +316,6 @@ namespace Game.Entities
|
||||
SetFloatValue(UnitFields.NegStat + (int)i, 0);
|
||||
}
|
||||
}
|
||||
public float GetResistanceBuffMods(SpellSchools school, bool positive)
|
||||
{
|
||||
return GetFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school);
|
||||
}
|
||||
public void SetResistanceBuffMods(SpellSchools school, bool positive, float val)
|
||||
{
|
||||
SetFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school, val);
|
||||
}
|
||||
public void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply)
|
||||
{
|
||||
ApplyModSignedFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school, val, apply);
|
||||
}
|
||||
public void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply)
|
||||
{
|
||||
ApplyPercentModFloatValue((positive ? UnitFields.ResistanceBuffModsPositive : UnitFields.ResistanceBuffModsNegative) + (int)school, val, apply);
|
||||
}
|
||||
|
||||
|
||||
public bool CanModifyStats()
|
||||
{
|
||||
@@ -634,13 +640,13 @@ namespace Game.Entities
|
||||
switch (attackType)
|
||||
{
|
||||
case WeaponAttackType.BaseAttack:
|
||||
chance = GetFloatValue(PlayerFields.CritPercentage);
|
||||
chance = GetFloatValue(ActivePlayerFields.CritPercentage);
|
||||
break;
|
||||
case WeaponAttackType.OffAttack:
|
||||
chance = GetFloatValue(PlayerFields.OffhandCritPercentage);
|
||||
chance = GetFloatValue(ActivePlayerFields.OffhandCritPercentage);
|
||||
break;
|
||||
case WeaponAttackType.RangedAttack:
|
||||
chance = GetFloatValue(PlayerFields.RangedCritPercentage);
|
||||
chance = GetFloatValue(ActivePlayerFields.RangedCritPercentage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -679,7 +685,7 @@ namespace Game.Entities
|
||||
float chance = 0.0f;
|
||||
float levelBonus = 0.0f;
|
||||
if (victim.IsTypeId(TypeId.Player))
|
||||
chance = victim.GetFloatValue(PlayerFields.DodgePercentage);
|
||||
chance = victim.GetFloatValue(ActivePlayerFields.DodgePercentage);
|
||||
else
|
||||
{
|
||||
if (!victim.IsTotem())
|
||||
@@ -723,7 +729,7 @@ namespace Game.Entities
|
||||
tmpitem = playerVictim.GetWeaponForAttack(WeaponAttackType.OffAttack, true);
|
||||
|
||||
if (tmpitem)
|
||||
chance = playerVictim.GetFloatValue(PlayerFields.ParryPercentage);
|
||||
chance = playerVictim.GetFloatValue(ActivePlayerFields.ParryPercentage);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -771,7 +777,7 @@ namespace Game.Entities
|
||||
{
|
||||
Item tmpitem = playerVictim.GetUseableItemByPos(InventorySlots.Bag0, EquipmentSlot.OffHand);
|
||||
if (tmpitem && !tmpitem.IsBroken() && tmpitem.GetTemplate().GetInventoryType() == InventoryType.Shield)
|
||||
chance = playerVictim.GetFloatValue(PlayerFields.BlockPercentage);
|
||||
chance = playerVictim.GetFloatValue(ActivePlayerFields.BlockPercentage);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -909,8 +915,7 @@ namespace Game.Entities
|
||||
{
|
||||
if (school > SpellSchools.Normal)
|
||||
{
|
||||
float value = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school);
|
||||
SetResistance(school, (int)value);
|
||||
base.UpdateResistances(school);
|
||||
|
||||
Pet pet = GetPet();
|
||||
if (pet != null)
|
||||
@@ -1025,18 +1030,18 @@ namespace Game.Entities
|
||||
// Magic damage modifiers implemented in Unit.SpellDamageBonusDone
|
||||
// This information for client side use only
|
||||
// Get healing bonus for all schools
|
||||
SetStatInt32Value(PlayerFields.ModHealingDonePos, (int)SpellBaseHealingBonusDone(SpellSchoolMask.All));
|
||||
SetStatInt32Value(ActivePlayerFields.ModHealingDonePos, (int)SpellBaseHealingBonusDone(SpellSchoolMask.All));
|
||||
// Get damage bonus for all schools
|
||||
var modDamageAuras = GetAuraEffectsByType(AuraType.ModDamageDone);
|
||||
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
|
||||
{
|
||||
SetInt32Value(PlayerFields.ModDamageDoneNeg + (int)i, modDamageAuras.Aggregate(0, (negativeMod, aurEff) =>
|
||||
SetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)i, modDamageAuras.Aggregate(0, (negativeMod, aurEff) =>
|
||||
{
|
||||
if (aurEff.GetAmount() < 0 && Convert.ToBoolean(aurEff.GetMiscValue() & (1 << (int)i)))
|
||||
negativeMod += aurEff.GetAmount();
|
||||
return negativeMod;
|
||||
}));
|
||||
SetStatInt32Value(PlayerFields.ModDamageDonePos + (int)i, SpellBaseDamageBonusDone((SpellSchoolMask)(1 << (int)i)) - GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)i));
|
||||
SetStatInt32Value(ActivePlayerFields.ModDamageDonePos + (int)i, SpellBaseDamageBonusDone((SpellSchoolMask)(1 << (int)i)) - GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)i));
|
||||
}
|
||||
|
||||
if (HasAuraType(AuraType.OverrideAttackPowerBySpPct))
|
||||
@@ -1085,11 +1090,11 @@ namespace Game.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
int minSpellPower = GetInt32Value(PlayerFields.ModHealingDonePos);
|
||||
int minSpellPower = GetInt32Value(ActivePlayerFields.ModHealingDonePos);
|
||||
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
|
||||
minSpellPower = Math.Min(minSpellPower, GetInt32Value(PlayerFields.ModDamageDonePos + (int)i));
|
||||
minSpellPower = Math.Min(minSpellPower, GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)i));
|
||||
|
||||
val2 = MathFunctions.CalculatePct(minSpellPower, GetFloatValue(PlayerFields.OverrideApBySpellPowerPercent));
|
||||
val2 = MathFunctions.CalculatePct(minSpellPower, GetFloatValue(ActivePlayerFields.OverrideApBySpellPowerPercent));
|
||||
}
|
||||
|
||||
SetModifierValue(unitMod, UnitModifierType.BaseValue, val2);
|
||||
@@ -1146,6 +1151,7 @@ namespace Game.Entities
|
||||
UnitMods unitMod = UnitMods.Armor;
|
||||
|
||||
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue); // base armor (from items)
|
||||
float baseValue = value;
|
||||
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT); // armor percent from items
|
||||
value += GetModifierValue(unitMod, UnitModifierType.TotalValue);
|
||||
|
||||
@@ -1159,7 +1165,7 @@ namespace Game.Entities
|
||||
|
||||
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
|
||||
|
||||
SetArmor((int)value);
|
||||
SetArmor((int)baseValue, (int)(value - baseValue));
|
||||
|
||||
Pet pet = GetPet();
|
||||
if (pet)
|
||||
@@ -1214,8 +1220,8 @@ namespace Game.Entities
|
||||
if (amount < 0)
|
||||
amount = 0;
|
||||
|
||||
uint oldRating = GetUInt32Value(PlayerFields.CombatRating1 + (int)cr);
|
||||
SetUInt32Value(PlayerFields.CombatRating1 + (int)cr, (uint)amount);
|
||||
uint oldRating = GetUInt32Value(ActivePlayerFields.CombatRating + (int)cr);
|
||||
SetUInt32Value(ActivePlayerFields.CombatRating + (int)cr, (uint)amount);
|
||||
|
||||
bool affectStats = CanModifyStats();
|
||||
|
||||
@@ -1314,13 +1320,13 @@ namespace Game.Entities
|
||||
{
|
||||
if (!CanUseMastery())
|
||||
{
|
||||
SetFloatValue(PlayerFields.Mastery, 0.0f);
|
||||
SetFloatValue(ActivePlayerFields.Mastery, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
float value = GetTotalAuraModifier(AuraType.Mastery);
|
||||
value += GetRatingBonusValue(CombatRating.Mastery);
|
||||
SetFloatValue(PlayerFields.Mastery, value);
|
||||
SetFloatValue(ActivePlayerFields.Mastery, value);
|
||||
|
||||
ChrSpecializationRecord chrSpec = CliDB.ChrSpecializationStorage.LookupByKey(GetUInt32Value(PlayerFields.CurrentSpecId));
|
||||
if (chrSpec == null)
|
||||
@@ -1349,7 +1355,7 @@ namespace Game.Entities
|
||||
public void UpdateVersatilityDamageDone()
|
||||
{
|
||||
// No proof that CR_VERSATILITY_DAMAGE_DONE is allways = PLAYER_VERSATILITY
|
||||
SetUInt32Value(PlayerFields.Versatility, GetUInt32Value(PlayerFields.CombatRating1 + (int)CombatRating.VersatilityDamageDone));
|
||||
SetUInt32Value(ActivePlayerFields.Versatility, GetUInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.VersatilityDamageDone));
|
||||
|
||||
if (GetClass() == Class.Hunter)
|
||||
UpdateDamagePhysical(WeaponAttackType.RangedAttack);
|
||||
@@ -1366,13 +1372,13 @@ namespace Game.Entities
|
||||
foreach (AuraEffect auraEffect in GetAuraEffectsByType(AuraType.ModHealingDonePercent))
|
||||
MathFunctions.AddPct(ref value, auraEffect.GetAmount());
|
||||
|
||||
SetStatFloatValue(PlayerFields.ModHealingDonePct, value);
|
||||
SetStatFloatValue(ActivePlayerFields.ModHealingDonePct, value);
|
||||
}
|
||||
|
||||
void UpdateArmorPenetration(int amount)
|
||||
{
|
||||
// Store Rating Value
|
||||
SetInt32Value(PlayerFields.CombatRating1 + (int)CombatRating.ArmorPenetration, amount);
|
||||
SetInt32Value(ActivePlayerFields.CombatRating + (int)CombatRating.ArmorPenetration, amount);
|
||||
}
|
||||
public void UpdateParryPercentage()
|
||||
{
|
||||
@@ -1410,7 +1416,7 @@ namespace Game.Entities
|
||||
|
||||
value = value < 0.0f ? 0.0f : value;
|
||||
}
|
||||
SetFloatValue(PlayerFields.ParryPercentage, value);
|
||||
SetFloatValue(ActivePlayerFields.ParryPercentage, value);
|
||||
}
|
||||
|
||||
public void UpdateDodgePercentage()
|
||||
@@ -1445,7 +1451,7 @@ namespace Game.Entities
|
||||
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsDodge) : value;
|
||||
|
||||
value = value < 0.0f ? 0.0f : value;
|
||||
SetStatFloatValue(PlayerFields.DodgePercentage, value);
|
||||
SetStatFloatValue(ActivePlayerFields.DodgePercentage, value);
|
||||
}
|
||||
public void UpdateBlockPercentage()
|
||||
{
|
||||
@@ -1465,31 +1471,31 @@ namespace Game.Entities
|
||||
|
||||
value = value < 0.0f ? 0.0f : value;
|
||||
}
|
||||
SetFloatValue(PlayerFields.BlockPercentage, value);
|
||||
SetFloatValue(ActivePlayerFields.BlockPercentage, value);
|
||||
}
|
||||
|
||||
public void UpdateCritPercentage(WeaponAttackType attType)
|
||||
{
|
||||
BaseModGroup modGroup;
|
||||
PlayerFields index;
|
||||
ActivePlayerFields index;
|
||||
CombatRating cr;
|
||||
|
||||
switch (attType)
|
||||
{
|
||||
case WeaponAttackType.OffAttack:
|
||||
modGroup = BaseModGroup.OffhandCritPercentage;
|
||||
index = PlayerFields.OffhandCritPercentage;
|
||||
index = ActivePlayerFields.OffhandCritPercentage;
|
||||
cr = CombatRating.CritMelee;
|
||||
break;
|
||||
case WeaponAttackType.RangedAttack:
|
||||
modGroup = BaseModGroup.RangedCritPercentage;
|
||||
index = PlayerFields.RangedCritPercentage;
|
||||
index = ActivePlayerFields.RangedCritPercentage;
|
||||
cr = CombatRating.CritRanged;
|
||||
break;
|
||||
case WeaponAttackType.BaseAttack:
|
||||
default:
|
||||
modGroup = BaseModGroup.CritPercentage;
|
||||
index = PlayerFields.CritPercentage;
|
||||
index = ActivePlayerFields.CritPercentage;
|
||||
cr = CombatRating.CritMelee;
|
||||
break;
|
||||
}
|
||||
@@ -1522,10 +1528,10 @@ namespace Game.Entities
|
||||
switch (attack)
|
||||
{
|
||||
case WeaponAttackType.BaseAttack:
|
||||
SetInt32Value(PlayerFields.Expertise, expertise);
|
||||
SetInt32Value(ActivePlayerFields.Expertise, expertise);
|
||||
break;
|
||||
case WeaponAttackType.OffAttack:
|
||||
SetInt32Value(PlayerFields.OffhandExpertise, expertise);
|
||||
SetInt32Value(ActivePlayerFields.OffhandExpertise, expertise);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -1617,7 +1623,7 @@ namespace Game.Entities
|
||||
crit += GetRatingBonusValue(CombatRating.CritSpell);
|
||||
|
||||
// Store crit value
|
||||
SetFloatValue(PlayerFields.SpellCritPercentage1, crit);
|
||||
SetFloatValue(ActivePlayerFields.SpellCritPercentage1, crit);
|
||||
}
|
||||
|
||||
public void UpdateMeleeHitChances()
|
||||
@@ -1682,7 +1688,7 @@ namespace Game.Entities
|
||||
|
||||
public void ApplySpellPenetrationBonus(int amount, bool apply)
|
||||
{
|
||||
ApplyModInt32Value(PlayerFields.ModTargetResistance, -amount, apply);
|
||||
ApplyModInt32Value(ActivePlayerFields.ModTargetResistance, -amount, apply);
|
||||
m_spellPenetrationItemMod += apply ? amount : -amount;
|
||||
}
|
||||
|
||||
@@ -1705,9 +1711,9 @@ namespace Game.Entities
|
||||
apply = _ModifyUInt32(apply, ref m_baseSpellPower, ref amount);
|
||||
|
||||
// For speed just update for client
|
||||
ApplyModUInt32Value(PlayerFields.ModHealingDonePos, amount, apply);
|
||||
ApplyModUInt32Value(ActivePlayerFields.ModHealingDonePos, amount, apply);
|
||||
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
|
||||
ApplyModUInt32Value(PlayerFields.ModDamageDonePos + i, amount, apply);
|
||||
ApplyModUInt32Value(ActivePlayerFields.ModDamageDonePos + i, amount, apply);
|
||||
|
||||
if (HasAuraType(AuraType.OverrideAttackPowerBySpPct))
|
||||
{
|
||||
@@ -1776,21 +1782,11 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void UpdateResistances(SpellSchools school)
|
||||
{
|
||||
if (school > SpellSchools.Normal)
|
||||
{
|
||||
float value = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school);
|
||||
SetResistance(school, (int)value);
|
||||
}
|
||||
else
|
||||
UpdateArmor();
|
||||
}
|
||||
|
||||
public override void UpdateArmor()
|
||||
{
|
||||
float baseValue = GetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue);
|
||||
float value = GetTotalAuraModValue(UnitMods.Armor);
|
||||
SetArmor((int)value);
|
||||
SetArmor((int)baseValue, (int)(value - baseValue));
|
||||
}
|
||||
|
||||
public override void UpdateMaxHealth()
|
||||
|
||||
@@ -1,515 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2018 CypherCore <http://github.com/CypherCore>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Game.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// The IndexMinPriorityQueue class represents an indexed priority queue of generic keys.
|
||||
/// </summary>
|
||||
/// <seealso href="http://algs4.cs.princeton.edu/24pq/IndexMinPQ.java.html">IndexMinPQ class from Princeton University's Java Algorithms</seealso>
|
||||
/// <typeparam name="T">Type must implement IComparable interface</typeparam>
|
||||
public class IndexMinPriorityQueue<T> where T : IComparable<T>
|
||||
{
|
||||
private readonly T[] _keys;
|
||||
private readonly int _maxSize;
|
||||
private readonly int[] _pq;
|
||||
private readonly int[] _qp;
|
||||
/// <summary>
|
||||
/// Constructs an empty indexed priority queue with indices between 0 and the specified maxSize - 1
|
||||
/// </summary>
|
||||
/// <param name="maxSize">The maximum size of the indexed priority queue</param>
|
||||
public IndexMinPriorityQueue(int maxSize)
|
||||
{
|
||||
_maxSize = maxSize;
|
||||
Size = 0;
|
||||
_keys = new T[_maxSize + 1];
|
||||
_pq = new int[_maxSize + 1];
|
||||
_qp = new int[_maxSize + 1];
|
||||
for (int i = 0; i < _maxSize; i++)
|
||||
{
|
||||
_qp[i] = -1;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The number of keys on this indexed priority queue
|
||||
/// </summary>
|
||||
public int Size { get; private set; }
|
||||
/// <summary>
|
||||
/// Is the indexed priority queue empty?
|
||||
/// </summary>
|
||||
/// <returns>True if the indexed priority queue is empty, false otherwise</returns>
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return Size == 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Is the specified parameter i an index on the priority queue?
|
||||
/// </summary>
|
||||
/// <param name="i">An index to check for on the priority queue</param>
|
||||
/// <returns>True if the specified parameter i is an index on the priority queue, false otherwise</returns>
|
||||
public bool Contains(int i)
|
||||
{
|
||||
return _qp[i] != -1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Associates the specified key with the specified index
|
||||
/// </summary>
|
||||
/// <param name="index">The index to associate the key with</param>
|
||||
/// <param name="key">The key to associate with the index</param>
|
||||
public void Insert(int index, T key)
|
||||
{
|
||||
Size++;
|
||||
_qp[index] = Size;
|
||||
_pq[Size] = index;
|
||||
_keys[index] = key;
|
||||
Swim(Size);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an index associated with a minimum key
|
||||
/// </summary>
|
||||
/// <returns>An index associated with a minimum key</returns>
|
||||
public int MinIndex()
|
||||
{
|
||||
return _pq[1];
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a minimum key
|
||||
/// </summary>
|
||||
/// <returns>A minimum key</returns>
|
||||
public T MinKey()
|
||||
{
|
||||
return _keys[_pq[1]];
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes a minimum key and returns its associated index
|
||||
/// </summary>
|
||||
/// <returns>An index associated with a minimum key that was removed</returns>
|
||||
public int DeleteMin()
|
||||
{
|
||||
int min = _pq[1];
|
||||
Exchange(1, Size--);
|
||||
Sink(1);
|
||||
_qp[min] = -1;
|
||||
_keys[_pq[Size + 1]] = default(T);
|
||||
_pq[Size + 1] = -1;
|
||||
return min;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the key associated with the specified index
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the key to return</param>
|
||||
/// <returns>The key associated with the specified index</returns>
|
||||
public T KeyAt(int index)
|
||||
{
|
||||
return _keys[index];
|
||||
}
|
||||
/// <summary>
|
||||
/// Change the key associated with the specified index to the specified value
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the key to change</param>
|
||||
/// <param name="key">Change the key associated with the specified index to this key</param>
|
||||
public void ChangeKey(int index, T key)
|
||||
{
|
||||
_keys[index] = key;
|
||||
Swim(_qp[index]);
|
||||
Sink(_qp[index]);
|
||||
}
|
||||
/// <summary>
|
||||
/// Decrease the key associated with the specified index to the specified value
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the key to decrease</param>
|
||||
/// <param name="key">Decrease the key associated with the specified index to this key</param>
|
||||
public void DecreaseKey(int index, T key)
|
||||
{
|
||||
_keys[index] = key;
|
||||
Swim(_qp[index]);
|
||||
}
|
||||
/// <summary>
|
||||
/// Increase the key associated with the specified index to the specified value
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the key to increase</param>
|
||||
/// <param name="key">Increase the key associated with the specified index to this key</param>
|
||||
public void IncreaseKey(int index, T key)
|
||||
{
|
||||
_keys[index] = key;
|
||||
Sink(_qp[index]);
|
||||
}
|
||||
/// <summary>
|
||||
/// Remove the key associated with the specified index
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the key to remove</param>
|
||||
public void Delete(int index)
|
||||
{
|
||||
int i = _qp[index];
|
||||
Exchange(i, Size--);
|
||||
Swim(i);
|
||||
Sink(i);
|
||||
_keys[index] = default(T);
|
||||
_qp[index] = -1;
|
||||
}
|
||||
private bool Greater(int i, int j)
|
||||
{
|
||||
return _keys[_pq[i]].CompareTo(_keys[_pq[j]]) > 0;
|
||||
}
|
||||
private void Exchange(int i, int j)
|
||||
{
|
||||
int swap = _pq[i];
|
||||
_pq[i] = _pq[j];
|
||||
_pq[j] = swap;
|
||||
_qp[_pq[i]] = i;
|
||||
_qp[_pq[j]] = j;
|
||||
}
|
||||
private void Swim(int k)
|
||||
{
|
||||
while (k > 1 && Greater(k / 2, k))
|
||||
{
|
||||
Exchange(k, k / 2);
|
||||
k = k / 2;
|
||||
}
|
||||
}
|
||||
private void Sink(int k)
|
||||
{
|
||||
while (2 * k <= Size)
|
||||
{
|
||||
int j = 2 * k;
|
||||
if (j < Size && Greater(j, j + 1))
|
||||
{
|
||||
j++;
|
||||
}
|
||||
if (!Greater(k, j))
|
||||
{
|
||||
break;
|
||||
}
|
||||
Exchange(k, j);
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The EdgeWeightedDigrpah class represents an edge-weighted directed graph of vertices named 0 through V-1, where each directed edge
|
||||
/// is of type DirectedEdge and has real-valued weight.
|
||||
/// </summary>
|
||||
/// <seealso href="http://algs4.cs.princeton.edu/44sp/EdgeWeightedDigraph.java.html">EdgeWeightedDigraph class from Princeton University's Java Algorithms</seealso>
|
||||
public class EdgeWeightedDigraph
|
||||
{
|
||||
private readonly LinkedList<DirectedEdge>[] _adjacent;
|
||||
/// <summary>
|
||||
/// Constructs an empty edge-weighted digraph with the specified number of vertices and 0 edges
|
||||
/// </summary>
|
||||
/// <param name="vertices">Number of vertices in the Graph</param>
|
||||
public EdgeWeightedDigraph(int vertices)
|
||||
{
|
||||
NumberOfVertices = vertices;
|
||||
NumberOfEdges = 0;
|
||||
_adjacent = new LinkedList<DirectedEdge>[NumberOfVertices];
|
||||
for (int v = 0; v < NumberOfVertices; v++)
|
||||
{
|
||||
_adjacent[v] = new LinkedList<DirectedEdge>();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The number of vertices in the edge-weighted digraph
|
||||
/// </summary>
|
||||
public int NumberOfVertices { get; private set; }
|
||||
/// <summary>
|
||||
/// The number of edges in the edge-weighted digraph
|
||||
/// </summary>
|
||||
public int NumberOfEdges { get; private set; }
|
||||
/// <summary>
|
||||
/// Adds the specified directed edge to the edge-weighted digraph
|
||||
/// </summary>
|
||||
/// <param name="edge">The DirectedEdge to add</param>
|
||||
/// <exception cref="ArgumentNullException">DirectedEdge cannot be null</exception>
|
||||
public void AddEdge(DirectedEdge edge)
|
||||
{
|
||||
if (edge == null)
|
||||
{
|
||||
throw new ArgumentNullException("edge", "DirectedEdge cannot be null");
|
||||
}
|
||||
|
||||
_adjacent[edge.From].AddLast(edge);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an IEnumerable of the DirectedEdges incident from the specified vertex
|
||||
/// </summary>
|
||||
/// <param name="vertex">The vertex to find incident DirectedEdges from</param>
|
||||
/// <returns>IEnumerable of the DirectedEdges incident from the specified vertex</returns>
|
||||
public IEnumerable<DirectedEdge> Adjacent(int vertex)
|
||||
{
|
||||
return _adjacent[vertex];
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an IEnumerable of all directed edges in the edge-weighted digraph
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable of of all directed edges in the edge-weighted digraph</returns>
|
||||
public IEnumerable<DirectedEdge> Edges()
|
||||
{
|
||||
for (int v = 0; v < NumberOfVertices; v++)
|
||||
{
|
||||
foreach (DirectedEdge edge in _adjacent[v])
|
||||
{
|
||||
yield return edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the number of directed edges incident from the specified vertex
|
||||
/// This is known as the outdegree of the vertex
|
||||
/// </summary>
|
||||
/// <param name="vertex">The vertex to find find the outdegree of</param>
|
||||
/// <returns>The number of directed edges incident from the specified vertex</returns>
|
||||
public int OutDegree(int vertex)
|
||||
{
|
||||
return _adjacent[vertex].Count;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current edge-weighted digraph
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string that represents the current edge-weighted digraph
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var formattedString = new StringBuilder();
|
||||
formattedString.AppendFormat("{0} vertices, {1} edges {2}", NumberOfVertices, NumberOfEdges, Environment.NewLine);
|
||||
for (int v = 0; v < NumberOfVertices; v++)
|
||||
{
|
||||
formattedString.AppendFormat("{0}: ", v);
|
||||
foreach (DirectedEdge edge in _adjacent[v])
|
||||
{
|
||||
formattedString.AppendFormat("{0} ", edge.To);
|
||||
}
|
||||
formattedString.AppendLine();
|
||||
}
|
||||
return formattedString.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The DirectedEdge class represents a weighted edge in an edge-weighted directed graph.
|
||||
/// </summary>
|
||||
/// <seealso href="http://algs4.cs.princeton.edu/44sp/DirectedEdge.java.html">DirectedEdge class from Princeton University's Java Algorithms</seealso>
|
||||
public class DirectedEdge
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs a directed edge from one specified vertex to another with the given weight
|
||||
/// </summary>
|
||||
/// <param name="from">The start vertex</param>
|
||||
/// <param name="to">The destination vertex</param>
|
||||
/// <param name="weight">The weight of the DirectedEdge</param>
|
||||
public DirectedEdge(uint from, uint to, double weight)
|
||||
{
|
||||
From = from;
|
||||
To = to;
|
||||
Weight = weight;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the destination vertex of the DirectedEdge
|
||||
/// </summary>
|
||||
public uint From { get; private set; }
|
||||
/// <summary>
|
||||
/// Returns the start vertex of the DirectedEdge
|
||||
/// </summary>
|
||||
public uint To { get; private set; }
|
||||
/// <summary>
|
||||
/// Returns the weight of the DirectedEdge
|
||||
/// </summary>
|
||||
public double Weight { get; private set; }
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current DirectedEdge
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A string that represents the current DirectedEdge
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"From: {From}, To: {To}, Weight: {Weight}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The DijkstraShortestPath class represents a data type for solving the single-source shortest paths problem
|
||||
/// in edge-weighted digraphs where the edge weights are non-negative
|
||||
/// </summary>
|
||||
/// <seealso href="http://algs4.cs.princeton.edu/44sp/DijkstraSP.java.html">DijkstraSP class from Princeton University's Java Algorithms</seealso>
|
||||
public class DijkstraShortestPath
|
||||
{
|
||||
private readonly double[] _distanceTo;
|
||||
private readonly DirectedEdge[] _edgeTo;
|
||||
private readonly IndexMinPriorityQueue<double> _priorityQueue;
|
||||
/// <summary>
|
||||
/// Computes a shortest paths tree from the specified sourceVertex to every other vertex in the edge-weighted directed graph
|
||||
/// </summary>
|
||||
/// <param name="graph">The edge-weighted directed graph</param>
|
||||
/// <param name="sourceVertex">The source vertex to compute the shortest paths tree from</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Throws an ArgumentOutOfRangeException if an edge weight is negative</exception>
|
||||
/// <exception cref="ArgumentNullException">Thrown if EdgeWeightedDigraph is null</exception>
|
||||
public DijkstraShortestPath(EdgeWeightedDigraph graph, int sourceVertex)
|
||||
{
|
||||
if (graph == null)
|
||||
{
|
||||
throw new ArgumentNullException("graph", "EdgeWeightedDigraph cannot be null");
|
||||
}
|
||||
|
||||
foreach (DirectedEdge edge in graph.Edges())
|
||||
{
|
||||
if (edge.Weight < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException($"Edge: '{edge}' has negative weight");
|
||||
}
|
||||
}
|
||||
|
||||
_distanceTo = new double[graph.NumberOfVertices];
|
||||
_edgeTo = new DirectedEdge[graph.NumberOfVertices];
|
||||
for (int v = 0; v < graph.NumberOfVertices; v++)
|
||||
{
|
||||
_distanceTo[v] = double.PositiveInfinity;
|
||||
}
|
||||
_distanceTo[sourceVertex] = 0.0;
|
||||
|
||||
_priorityQueue = new IndexMinPriorityQueue<double>(graph.NumberOfVertices);
|
||||
_priorityQueue.Insert(sourceVertex, _distanceTo[sourceVertex]);
|
||||
while (!_priorityQueue.IsEmpty())
|
||||
{
|
||||
int v = _priorityQueue.DeleteMin();
|
||||
foreach (DirectedEdge edge in graph.Adjacent(v))
|
||||
{
|
||||
Relax(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Relax(DirectedEdge edge)
|
||||
{
|
||||
uint v = edge.From;
|
||||
uint w = edge.To;
|
||||
if (_distanceTo[w] > _distanceTo[v] + edge.Weight)
|
||||
{
|
||||
_distanceTo[w] = _distanceTo[v] + edge.Weight;
|
||||
_edgeTo[w] = edge;
|
||||
if (_priorityQueue.Contains((int)w))
|
||||
{
|
||||
_priorityQueue.DecreaseKey((int)w, _distanceTo[w]);
|
||||
}
|
||||
else
|
||||
{
|
||||
_priorityQueue.Insert((int)w, _distanceTo[w]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the length of a shortest path from the sourceVertex to the specified destinationVertex
|
||||
/// </summary>
|
||||
/// <param name="destinationVertex">The destination vertex to find a shortest path to</param>
|
||||
/// <returns>The length of a shortest path from the sourceVertex to the specified destinationVertex or double.PositiveInfinity if no such path exists</returns>
|
||||
public double DistanceTo(int destinationVertex)
|
||||
{
|
||||
return _distanceTo[destinationVertex];
|
||||
}
|
||||
/// <summary>
|
||||
/// Is there a path from the sourceVertex to the specified destinationVertex?
|
||||
/// </summary>
|
||||
/// <param name="destinationVertex">The destination vertex to see if there is a path to</param>
|
||||
/// <returns>True if there is a path from the sourceVertex to the specified destinationVertex, false otherwise</returns>
|
||||
public bool HasPathTo(int destinationVertex)
|
||||
{
|
||||
return _distanceTo[destinationVertex] < double.PositiveInfinity;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex
|
||||
/// </summary>
|
||||
/// <param name="destinationVertex">The destination vertex to find a shortest path to</param>
|
||||
/// <returns>IEnumerable of DirectedEdges representing a shortest path from the sourceVertex to the specified destinationVertex</returns>
|
||||
public IEnumerable<DirectedEdge> PathTo(int destinationVertex)
|
||||
{
|
||||
if (!HasPathTo(destinationVertex))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var path = new Stack<DirectedEdge>();
|
||||
for (DirectedEdge edge = _edgeTo[destinationVertex]; edge != null; edge = _edgeTo[edge.From])
|
||||
{
|
||||
path.Push(edge);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
// TODO: This method should be private and should be called from the bottom of the constructor
|
||||
/// <summary>
|
||||
/// check optimality conditions:
|
||||
/// </summary>
|
||||
/// <param name="graph">The edge-weighted directed graph</param>
|
||||
/// <param name="sourceVertex">The source vertex to check optimality conditions from</param>
|
||||
/// <returns>True if all optimality conditions are met, false otherwise</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown on null EdgeWeightedDigraph</exception>
|
||||
public bool Check(EdgeWeightedDigraph graph, int sourceVertex)
|
||||
{
|
||||
if (graph == null)
|
||||
{
|
||||
throw new ArgumentNullException("graph", "EdgeWeightedDigraph cannot be null");
|
||||
}
|
||||
|
||||
if (_distanceTo[sourceVertex] != 0.0 || _edgeTo[sourceVertex] != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int v = 0; v < graph.NumberOfVertices; v++)
|
||||
{
|
||||
if (v == sourceVertex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (_edgeTo[v] == null && _distanceTo[v] != double.PositiveInfinity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int v = 0; v < graph.NumberOfVertices; v++)
|
||||
{
|
||||
foreach (DirectedEdge edge in graph.Adjacent(v))
|
||||
{
|
||||
uint w = edge.To;
|
||||
if (_distanceTo[v] + edge.Weight < _distanceTo[w])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int w = 0; w < graph.NumberOfVertices; w++)
|
||||
{
|
||||
if (_edgeTo[w] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
DirectedEdge edge = _edgeTo[w];
|
||||
uint v = edge.From;
|
||||
if (w != edge.To)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (_distanceTo[v] + edge.Weight != _distanceTo[w])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Framework.Algorithms;
|
||||
using Framework.Collections;
|
||||
using Framework.Constants;
|
||||
using Framework.GameMath;
|
||||
using Game.DataStorage;
|
||||
@@ -25,11 +27,15 @@ namespace Game.Entities
|
||||
{
|
||||
public class TaxiPathGraph : Singleton<TaxiPathGraph>
|
||||
{
|
||||
EdgeWeightedDigraph m_graph;
|
||||
List<TaxiNodesRecord> m_nodesByVertex = new List<TaxiNodesRecord>();
|
||||
Dictionary<uint, uint> m_verticesByNode = new Dictionary<uint, uint>();
|
||||
|
||||
TaxiPathGraph() { }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
if (GetVertexCount() > 0)
|
||||
if (m_graph.NumberOfVertices > 0)
|
||||
return;
|
||||
|
||||
List<Tuple<Tuple<uint, uint>, uint>> edges = new List<Tuple<Tuple<uint, uint>, uint>>();
|
||||
@@ -44,7 +50,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// create graph
|
||||
m_graph = new EdgeWeightedDigraph(GetVertexCount());
|
||||
m_graph = new EdgeWeightedDigraph(m_nodesByVertex.Count);
|
||||
|
||||
for (int j = 0; j < edges.Count; ++j)
|
||||
{
|
||||
@@ -54,24 +60,21 @@ namespace Game.Entities
|
||||
|
||||
uint GetNodeIDFromVertexID(uint vertexID)
|
||||
{
|
||||
if (vertexID < m_vertices.Length)
|
||||
return m_vertices[vertexID].Id;
|
||||
if (vertexID < m_nodesByVertex.Count)
|
||||
return m_nodesByVertex[(int)vertexID].Id;
|
||||
|
||||
return uint.MaxValue;
|
||||
}
|
||||
|
||||
uint GetVertexIDFromNodeID(TaxiNodesRecord node)
|
||||
{
|
||||
return node.CharacterBitNumber;
|
||||
return m_verticesByNode.ContainsKey(node.Id) ? m_verticesByNode[node.Id] : uint.MaxValue;
|
||||
}
|
||||
|
||||
int GetVertexCount()
|
||||
void GetTaxiMapPosition(Vector3 position, int mapId, out Vector2 uiMapPosition, out int uiMapId)
|
||||
{
|
||||
if (m_graph == null)
|
||||
return m_vertices.Length;
|
||||
|
||||
//So we can use this function for readability, we define either max defined vertices or already loaded in graph count
|
||||
return m_vertices.Length;// Math.Max(m_graph.getNumberOfVertices(), m_vertices.Length);
|
||||
if (!Global.DB2Mgr.GetUiMapPosition(position.X, position.Y, position.Z, mapId, 0, 0, 0, UiMapSystem.Adventure, false, out uiMapId, out uiMapPosition))
|
||||
Global.DB2Mgr.GetUiMapPosition(position.X, position.Y, position.Z, mapId, 0, 0, 0, UiMapSystem.Taxi, false, out uiMapId, out uiMapPosition);
|
||||
}
|
||||
|
||||
void AddVerticeAndEdgeFromNodeInfo(TaxiNodesRecord from, TaxiNodesRecord to, uint pathId, List<Tuple<Tuple<uint, uint>, uint>> edges)
|
||||
@@ -102,19 +105,19 @@ namespace Game.Entities
|
||||
if (nodes[i - 1].Flags.HasAnyFlag(TaxiPathNodeFlags.Teleport))
|
||||
continue;
|
||||
|
||||
uint map1, map2;
|
||||
int uiMap1, uiMap2;
|
||||
Vector2 pos1, pos2;
|
||||
|
||||
Global.DB2Mgr.DeterminaAlternateMapPosition(nodes[i - 1].ContinentID, nodes[i - 1].Loc.X, nodes[i - 1].Loc.Y, nodes[i - 1].Loc.Z, out map1, out pos1);
|
||||
Global.DB2Mgr.DeterminaAlternateMapPosition(nodes[i].ContinentID, nodes[i].Loc.X, nodes[i].Loc.Y, nodes[i].Loc.Z, out map2, out pos2);
|
||||
GetTaxiMapPosition(nodes[i - 1].Loc, nodes[i - 1].ContinentID, out pos1, out uiMap1);
|
||||
GetTaxiMapPosition(nodes[i].Loc, nodes[i].ContinentID, out pos2, out uiMap2);
|
||||
|
||||
if (map1 != map2)
|
||||
if (uiMap1 != uiMap2)
|
||||
continue;
|
||||
|
||||
totalDist += (float)Math.Sqrt((float)Math.Pow(pos2.X - pos1.X, 2) + (float)Math.Pow(pos2.Y - pos1.Y, 2) + (float)Math.Pow(nodes[i].Loc.Z - nodes[i - 1].Loc.Z, 2));
|
||||
totalDist += (float)Math.Sqrt((float)Math.Pow(pos2.X - pos1.X, 2) + (float)Math.Pow(pos2.Y - pos1.Y, 2));
|
||||
}
|
||||
|
||||
uint dist = (uint)totalDist;
|
||||
uint dist = (uint)(totalDist * 32767.0f);
|
||||
if (dist > 0xFFFF)
|
||||
dist = 0xFFFF;
|
||||
|
||||
@@ -152,7 +155,7 @@ namespace Game.Entities
|
||||
foreach (var edge in path)
|
||||
{
|
||||
//todo test me No clue about this....
|
||||
var To = m_vertices[edge.To];
|
||||
var To = m_nodesByVertex[(int)edge.To];
|
||||
TaxiNodeFlags requireFlag = (player.GetTeam() == Team.Alliance) ? TaxiNodeFlags.Alliance : TaxiNodeFlags.Horde;
|
||||
if (!To.Flags.HasAnyFlag(requireFlag))
|
||||
continue;
|
||||
@@ -169,19 +172,27 @@ namespace Game.Entities
|
||||
return shortestPath.Count;
|
||||
}
|
||||
|
||||
uint CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesRecord node)
|
||||
//todo test me
|
||||
public void GetReachableNodesMask(TaxiNodesRecord from, byte[] mask)
|
||||
{
|
||||
//Check if we need a new one or if it may be already created
|
||||
if (m_vertices.Length <= node.CharacterBitNumber)
|
||||
Array.Resize(ref m_vertices, (int)node.CharacterBitNumber + 1);
|
||||
|
||||
m_vertices[node.CharacterBitNumber] = node;
|
||||
return node.CharacterBitNumber;
|
||||
DepthFirstSearch depthFirst = new DepthFirstSearch(m_graph, GetVertexIDFromNodeID(from), vertex =>
|
||||
{
|
||||
TaxiNodesRecord taxiNode = CliDB.TaxiNodesStorage.LookupByKey(GetNodeIDFromVertexID(vertex));
|
||||
if (taxiNode != null)
|
||||
mask[(taxiNode.Id - 1) / 8] |= (byte)(1 << (int)((taxiNode.Id - 1) % 8));
|
||||
});
|
||||
}
|
||||
|
||||
TaxiNodesRecord[] m_vertices = new TaxiNodesRecord[0];
|
||||
EdgeWeightedDigraph m_graph;
|
||||
uint CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesRecord node)
|
||||
{
|
||||
if (!m_verticesByNode.ContainsKey(node.Id))
|
||||
{
|
||||
m_verticesByNode.Add(node.Id, (uint)m_nodesByVertex.Count);
|
||||
m_nodesByVertex.Add(node);
|
||||
}
|
||||
|
||||
return m_verticesByNode[node.Id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -367,7 +367,7 @@ namespace Game.Entities
|
||||
// Shaman pet
|
||||
public bool IsSpiritWolf() { return GetEntry() == (uint)PetEntry.SpiritWolf; } // Spirit wolf from feral spirits
|
||||
|
||||
Unit m_owner;
|
||||
protected Unit m_owner;
|
||||
float m_followAngle;
|
||||
}
|
||||
|
||||
@@ -467,8 +467,12 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// Resistance
|
||||
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
|
||||
SetModifierValue(UnitMods.ResistanceStart + i, UnitModifierType.BaseValue, cinfo.Resistance[i]);
|
||||
// Hunters pet should not inherit resistances from creature_template, they have separate auras for that
|
||||
if (!IsHunterPet())
|
||||
{
|
||||
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
|
||||
SetModifierValue(UnitMods.ResistanceStart + i, UnitModifierType.BaseValue, cinfo.Resistance[i]);
|
||||
}
|
||||
|
||||
// Health, Mana or Power, Armor
|
||||
PetLevelInfo pInfo = Global.ObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
|
||||
@@ -513,8 +517,8 @@ namespace Game.Entities
|
||||
case PetType.Summon:
|
||||
{
|
||||
// the damage bonus used for pets is either fire or shadow damage, whatever is higher
|
||||
int fire = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Fire);
|
||||
int shadow = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow);
|
||||
int fire = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire);
|
||||
int shadow = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow);
|
||||
int val = (fire > shadow) ? fire : shadow;
|
||||
if (val < 0)
|
||||
val = 0;
|
||||
@@ -754,13 +758,18 @@ namespace Game.Entities
|
||||
{
|
||||
if (school > SpellSchools.Normal)
|
||||
{
|
||||
float value = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school);
|
||||
float baseValue = GetModifierValue( UnitMods.ResistanceStart + (int)school, UnitModifierType.BaseValue);
|
||||
float bonusValue = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school) - baseValue;
|
||||
|
||||
// hunter and warlock pets gain 40% of owner's resistance
|
||||
if (IsPet())
|
||||
value += MathFunctions.CalculatePct(GetOwner().GetResistance(school), 40);
|
||||
{
|
||||
baseValue += (float)MathFunctions.CalculatePct(m_owner.GetResistance(school), 40);
|
||||
bonusValue += (float)MathFunctions.CalculatePct(m_owner.GetBonusResistanceMod(school), 40);
|
||||
}
|
||||
|
||||
SetResistance(school, (int)value);
|
||||
SetResistance(school, (int)baseValue);
|
||||
SetBonusResistanceMod(school, (int)bonusValue);
|
||||
}
|
||||
else
|
||||
UpdateArmor();
|
||||
@@ -768,6 +777,7 @@ namespace Game.Entities
|
||||
|
||||
public override void UpdateArmor()
|
||||
{
|
||||
float baseValue = 0.0f;
|
||||
float value = 0.0f;
|
||||
float bonus_armor = 0.0f;
|
||||
UnitMods unitMod = UnitMods.Armor;
|
||||
@@ -779,11 +789,12 @@ namespace Game.Entities
|
||||
bonus_armor = GetOwner().GetArmor();
|
||||
|
||||
value = GetModifierValue(unitMod, UnitModifierType.BaseValue);
|
||||
baseValue = value;
|
||||
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
|
||||
value += GetModifierValue(unitMod, UnitModifierType.TotalValue) + bonus_armor;
|
||||
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
|
||||
|
||||
SetArmor((int)value);
|
||||
SetArmor((int)baseValue, (int)(value - baseValue));
|
||||
}
|
||||
|
||||
public override void UpdateMaxHealth()
|
||||
@@ -877,8 +888,8 @@ namespace Game.Entities
|
||||
//demons benefit from warlocks shadow or fire damage
|
||||
else if (IsPet())
|
||||
{
|
||||
int fire = owner.GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - owner.GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
|
||||
int shadow = owner.GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow) - owner.GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Shadow);
|
||||
int fire = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
|
||||
int shadow = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Shadow) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Shadow);
|
||||
int maximum = (fire > shadow) ? fire : shadow;
|
||||
if (maximum < 0)
|
||||
maximum = 0;
|
||||
@@ -888,7 +899,7 @@ namespace Game.Entities
|
||||
//water elementals benefit from mage's frost damage
|
||||
else if (GetEntry() == ENTRY_WATER_ELEMENTAL)
|
||||
{
|
||||
int frost = owner.GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Frost) - owner.GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Frost);
|
||||
int frost = owner.GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Frost) - owner.GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Frost);
|
||||
if (frost < 0)
|
||||
frost = 0;
|
||||
SetBonusDamage((int)(frost * 0.4f));
|
||||
@@ -921,14 +932,14 @@ namespace Game.Entities
|
||||
//force of nature
|
||||
if (GetEntry() == ENTRY_TREANT)
|
||||
{
|
||||
int spellDmg = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Nature) - GetOwner().GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Nature);
|
||||
int spellDmg = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Nature) - GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Nature);
|
||||
if (spellDmg > 0)
|
||||
bonusDamage = spellDmg * 0.09f;
|
||||
}
|
||||
//greater fire elemental
|
||||
else if (GetEntry() == ENTRY_FIRE_ELEMENTAL)
|
||||
{
|
||||
int spellDmg = GetOwner().GetInt32Value(PlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - GetOwner().GetInt32Value(PlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
|
||||
int spellDmg = GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDonePos + (int)SpellSchools.Fire) - GetOwner().GetInt32Value(ActivePlayerFields.ModDamageDoneNeg + (int)SpellSchools.Fire);
|
||||
if (spellDmg > 0)
|
||||
bonusDamage = spellDmg * 0.4f;
|
||||
}
|
||||
@@ -957,7 +968,7 @@ namespace Game.Entities
|
||||
{
|
||||
m_bonusSpellDamage = damage;
|
||||
if (GetOwner().IsTypeId(TypeId.Player))
|
||||
GetOwner().SetUInt32Value(PlayerFields.PetSpellPower, (uint)damage);
|
||||
GetOwner().SetUInt32Value(ActivePlayerFields.PetSpellPower, (uint)damage);
|
||||
}
|
||||
|
||||
public int GetBonusDamage() { return m_bonusSpellDamage; }
|
||||
|
||||
@@ -66,7 +66,9 @@ namespace Game.Entities
|
||||
{
|
||||
_isMoving = true;
|
||||
|
||||
m_updateFlag = UpdateFlag.Transport | UpdateFlag.StationaryPosition | UpdateFlag.Rotation;
|
||||
m_updateFlag.ServerTime = true;
|
||||
m_updateFlag.Stationary = true;
|
||||
m_updateFlag.Rotation = true;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
|
||||
@@ -622,6 +622,7 @@ namespace Game.Entities
|
||||
damageInfo.damageSchoolMask = (uint)GetMeleeDamageSchoolMask();
|
||||
damageInfo.attackType = attType;
|
||||
damageInfo.damage = 0;
|
||||
damageInfo.originalDamage = 0;
|
||||
damageInfo.cleanDamage = 0;
|
||||
damageInfo.absorb = 0;
|
||||
damageInfo.resist = 0;
|
||||
@@ -835,7 +836,7 @@ namespace Game.Entities
|
||||
DamageInfo damageInfo1 = new DamageInfo(this, victim, damage, spellInfo, spellInfo.GetSchoolMask(), DamageEffectType.SpellDirect, WeaponAttackType.BaseAttack);
|
||||
victim.CalcAbsorbResist(damageInfo1);
|
||||
damage = damageInfo1.GetDamage();
|
||||
// No Unit.CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that
|
||||
|
||||
victim.DealDamageMods(this, ref damage);
|
||||
|
||||
SpellDamageShield damageShield = new SpellDamageShield();
|
||||
@@ -843,6 +844,7 @@ namespace Game.Entities
|
||||
damageShield.Defender = GetGUID();
|
||||
damageShield.SpellID = spellInfo.Id;
|
||||
damageShield.TotalDamage = damage;
|
||||
damageShield.OriginalDamage = (int)damageInfo.originalDamage;
|
||||
damageShield.OverKill = (uint)Math.Max(damage - GetHealth(), 0);
|
||||
damageShield.SchoolMask = (uint)spellInfo.SchoolMask;
|
||||
damageShield.LogAbsorbed = damageInfo1.GetAbsorb();
|
||||
@@ -1183,6 +1185,7 @@ namespace Game.Entities
|
||||
dmgInfo.attacker = this;
|
||||
dmgInfo.target = target;
|
||||
dmgInfo.damage = Damage - AbsorbDamage - Resist - BlockedAmount;
|
||||
dmgInfo.originalDamage = Damage;
|
||||
dmgInfo.damageSchoolMask = (uint)damageSchoolMask;
|
||||
dmgInfo.absorb = AbsorbDamage;
|
||||
dmgInfo.resist = Resist;
|
||||
@@ -1197,6 +1200,7 @@ namespace Game.Entities
|
||||
packet.AttackerGUID = damageInfo.attacker.GetGUID();
|
||||
packet.VictimGUID = damageInfo.target.GetGUID();
|
||||
packet.Damage = (int)damageInfo.damage;
|
||||
packet.OriginalDamage = (int)damageInfo.originalDamage;
|
||||
int overkill = (int)(damageInfo.damage - damageInfo.target.GetHealth());
|
||||
packet.OverDamage = (overkill < 0 ? -1 : overkill);
|
||||
|
||||
@@ -1212,9 +1216,9 @@ namespace Game.Entities
|
||||
packet.BlockAmount = (int)damageInfo.blocked_amount;
|
||||
packet.LogData.Initialize(damageInfo.attacker);
|
||||
|
||||
SandboxScalingData sandboxScalingData = new SandboxScalingData();
|
||||
if (sandboxScalingData.GenerateDataForUnits(damageInfo.attacker, damageInfo.target))
|
||||
packet.SandboxScaling = sandboxScalingData;
|
||||
ContentTuningParams contentTuningParams = new ContentTuningParams();
|
||||
if (contentTuningParams.GenerateDataForUnits(damageInfo.attacker, damageInfo.target))
|
||||
packet.ContentTuning = contentTuningParams;
|
||||
|
||||
SendCombatLogMessage(packet);
|
||||
}
|
||||
@@ -1321,6 +1325,8 @@ namespace Game.Entities
|
||||
unit.SetInCombatState(PvP, enemy);
|
||||
unit.SetFlag(UnitFields.Flags, UnitFlags.PetInCombat);
|
||||
}
|
||||
|
||||
ProcSkillsAndAuras(enemy, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
|
||||
}
|
||||
|
||||
internal void SendCombatLogMessage(CombatLogServerPacket combatLog)
|
||||
@@ -1770,6 +1776,7 @@ namespace Game.Entities
|
||||
damageInfo.damageSchoolMask = (uint)SpellSchoolMask.Normal;
|
||||
damageInfo.attackType = attackType;
|
||||
damageInfo.damage = 0;
|
||||
damageInfo.originalDamage = 0;
|
||||
damageInfo.cleanDamage = 0;
|
||||
damageInfo.absorb = 0;
|
||||
damageInfo.resist = 0;
|
||||
@@ -1838,18 +1845,20 @@ namespace Game.Entities
|
||||
case MeleeHitOutcome.Evade:
|
||||
damageInfo.HitInfo |= HitInfo.Miss | HitInfo.SwingNoHitSound;
|
||||
damageInfo.TargetState = VictimState.Evades;
|
||||
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
damageInfo.damage = 0;
|
||||
damageInfo.cleanDamage = 0;
|
||||
return;
|
||||
case MeleeHitOutcome.Miss:
|
||||
damageInfo.HitInfo |= HitInfo.Miss;
|
||||
damageInfo.TargetState = VictimState.Intact;
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
damageInfo.damage = 0;
|
||||
damageInfo.cleanDamage = 0;
|
||||
break;
|
||||
case MeleeHitOutcome.Normal:
|
||||
damageInfo.TargetState = VictimState.Hit;
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
break;
|
||||
case MeleeHitOutcome.Crit:
|
||||
damageInfo.HitInfo |= HitInfo.CriticalHit;
|
||||
@@ -1862,19 +1871,25 @@ namespace Game.Entities
|
||||
|
||||
if (mod != 0)
|
||||
MathFunctions.AddPct(ref damageInfo.damage, mod);
|
||||
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
break;
|
||||
case MeleeHitOutcome.Parry:
|
||||
damageInfo.TargetState = VictimState.Parry;
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
damageInfo.cleanDamage += damageInfo.damage;
|
||||
damageInfo.damage = 0;
|
||||
break;
|
||||
case MeleeHitOutcome.Dodge:
|
||||
damageInfo.TargetState = VictimState.Dodge;
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
damageInfo.cleanDamage += damageInfo.damage;
|
||||
damageInfo.damage = 0;
|
||||
break;
|
||||
case MeleeHitOutcome.Block:
|
||||
damageInfo.TargetState = VictimState.Hit;
|
||||
damageInfo.HitInfo |= HitInfo.Block;
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
// 30% damage blocked, double blocked amount if block is critical
|
||||
damageInfo.blocked_amount = MathFunctions.CalculatePct(damageInfo.damage, damageInfo.target.isBlockCritical() ? damageInfo.target.GetBlockPercent() * 2 : damageInfo.target.GetBlockPercent());
|
||||
damageInfo.damage -= damageInfo.blocked_amount;
|
||||
@@ -1883,6 +1898,7 @@ namespace Game.Entities
|
||||
case MeleeHitOutcome.Glancing:
|
||||
damageInfo.HitInfo |= HitInfo.Glancing;
|
||||
damageInfo.TargetState = VictimState.Hit;
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
int leveldif = (int)victim.getLevel() - (int)getLevel();
|
||||
if (leveldif > 3)
|
||||
leveldif = 3;
|
||||
@@ -1896,6 +1912,7 @@ namespace Game.Entities
|
||||
damageInfo.TargetState = VictimState.Hit;
|
||||
// 150% normal damage
|
||||
damageInfo.damage += (damageInfo.damage / 2);
|
||||
damageInfo.originalDamage = damageInfo.damage;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2495,6 +2512,7 @@ namespace Game.Entities
|
||||
CleanDamage cleanDamage = new CleanDamage(splitDamage, 0, WeaponAttackType.BaseAttack, MeleeHitOutcome.Normal);
|
||||
DealDamage(caster, splitDamage, cleanDamage, DamageEffectType.Direct, damageInfo.GetSchoolMask(), itr.GetSpellInfo(), false);
|
||||
log.damage = splitDamage;
|
||||
log.originalDamage = splitDamage;
|
||||
log.absorb = split_absorb;
|
||||
SendSpellNonMeleeDamageLog(log);
|
||||
|
||||
@@ -2682,7 +2700,7 @@ namespace Game.Entities
|
||||
for (var i = SpellSchools.Holy; i < SpellSchools.Max; ++i)
|
||||
{
|
||||
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << (int)i)))
|
||||
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(PlayerFields.ModDamageDonePct + (int)i));
|
||||
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + (int)i));
|
||||
}
|
||||
|
||||
DoneTotalMod *= maxModDamagePercentSchool;
|
||||
|
||||
@@ -226,6 +226,7 @@ namespace Game.Entities
|
||||
m_attacker = attacker;
|
||||
m_victim = victim;
|
||||
m_damage = damage;
|
||||
m_originalDamage = damage;
|
||||
m_spellInfo = spellInfo;
|
||||
m_schoolMask = schoolMask;
|
||||
m_damageType = damageType;
|
||||
@@ -237,6 +238,7 @@ namespace Game.Entities
|
||||
m_attacker = dmgInfo.attacker;
|
||||
m_victim = dmgInfo.target;
|
||||
m_damage = dmgInfo.damage;
|
||||
m_originalDamage = dmgInfo.damage;
|
||||
m_spellInfo = null;
|
||||
m_schoolMask = (SpellSchoolMask)dmgInfo.damageSchoolMask;
|
||||
m_damageType = DamageEffectType.Direct;
|
||||
@@ -357,6 +359,7 @@ namespace Game.Entities
|
||||
DamageEffectType GetDamageType() { return m_damageType; }
|
||||
public WeaponAttackType GetAttackType() { return m_attackType; }
|
||||
public uint GetDamage() { return m_damage; }
|
||||
public uint GetOriginalDamage() { return m_originalDamage; }
|
||||
public uint GetAbsorb() { return m_absorb; }
|
||||
public uint GetResist() { return m_resist; }
|
||||
uint GetBlock() { return m_block; }
|
||||
@@ -365,6 +368,7 @@ namespace Game.Entities
|
||||
Unit m_attacker;
|
||||
Unit m_victim;
|
||||
uint m_damage;
|
||||
uint m_originalDamage;
|
||||
SpellInfo m_spellInfo;
|
||||
SpellSchoolMask m_schoolMask;
|
||||
DamageEffectType m_damageType;
|
||||
@@ -382,6 +386,7 @@ namespace Game.Entities
|
||||
_healer = healer;
|
||||
_target = target;
|
||||
_heal = heal;
|
||||
_originalHeal = heal;
|
||||
_spellInfo = spellInfo;
|
||||
_schoolMask = schoolMask;
|
||||
}
|
||||
@@ -400,6 +405,7 @@ namespace Game.Entities
|
||||
public Unit GetHealer() { return _healer; }
|
||||
public Unit GetTarget() { return _target; }
|
||||
public uint GetHeal() { return _heal; }
|
||||
public uint GetOriginalHeal() { return _originalHeal; }
|
||||
public uint GetEffectiveHeal() { return _effectiveHeal; }
|
||||
public uint GetAbsorb() { return _absorb; }
|
||||
public SpellInfo GetSpellInfo() { return _spellInfo; }
|
||||
@@ -409,6 +415,7 @@ namespace Game.Entities
|
||||
Unit _healer;
|
||||
Unit _target;
|
||||
uint _heal;
|
||||
uint _originalHeal;
|
||||
uint _effectiveHeal;
|
||||
uint _absorb;
|
||||
SpellInfo _spellInfo;
|
||||
@@ -422,6 +429,7 @@ namespace Game.Entities
|
||||
public Unit target { get; set; } // Target for damage
|
||||
public uint damageSchoolMask { get; set; }
|
||||
public uint damage;
|
||||
public uint originalDamage;
|
||||
public uint absorb;
|
||||
public uint resist;
|
||||
public uint blocked_amount { get; set; }
|
||||
@@ -454,6 +462,7 @@ namespace Game.Entities
|
||||
public uint SpellId;
|
||||
public uint SpellXSpellVisualID;
|
||||
public uint damage;
|
||||
public uint originalDamage;
|
||||
public SpellSchoolMask schoolMask;
|
||||
public uint absorb;
|
||||
public uint resist;
|
||||
@@ -528,10 +537,11 @@ namespace Game.Entities
|
||||
|
||||
public class SpellPeriodicAuraLogInfo
|
||||
{
|
||||
public SpellPeriodicAuraLogInfo(AuraEffect _auraEff, uint _damage, int _overDamage, uint _absorb, uint _resist, float _multiplier, bool _critical)
|
||||
public SpellPeriodicAuraLogInfo(AuraEffect _auraEff, uint _damage, uint _originalDamage, uint _overDamage, uint _absorb, uint _resist, float _multiplier, bool _critical)
|
||||
{
|
||||
auraEff = _auraEff;
|
||||
damage = _damage;
|
||||
originalDamage = _originalDamage;
|
||||
overDamage = _overDamage;
|
||||
absorb = _absorb;
|
||||
resist = _resist;
|
||||
@@ -541,7 +551,8 @@ namespace Game.Entities
|
||||
|
||||
public AuraEffect auraEff;
|
||||
public uint damage;
|
||||
public int overDamage; // overkill/overheal
|
||||
public uint originalDamage;
|
||||
public uint overDamage; // overkill/overheal
|
||||
public uint absorb;
|
||||
public uint resist;
|
||||
public float multiplier;
|
||||
|
||||
@@ -543,7 +543,8 @@ namespace Game.Entities
|
||||
return false;
|
||||
}
|
||||
|
||||
bool turn = (GetOrientation() != orientation);
|
||||
// Check if angular distance changed
|
||||
bool turn = MathFunctions.fuzzyGt(Math.PI - Math.Abs(Math.Abs(GetOrientation() - orientation) - Math.PI), 0.0f);
|
||||
// G3D::fuzzyEq won't help here, in some cases magnitudes differ by a little more than G3D::eps, but should be considered equal
|
||||
bool relocated = (teleport ||
|
||||
Math.Abs(GetPositionX() - x) > 0.001f ||
|
||||
@@ -1290,6 +1291,12 @@ namespace Game.Entities
|
||||
player.UnsummonPetTemporaryIfAny();
|
||||
}
|
||||
|
||||
// if we have charmed npc, stun him also (everywhere)
|
||||
Unit charm = player.GetCharm();
|
||||
if (charm)
|
||||
if (charm.GetTypeId() == TypeId.Unit)
|
||||
charm.SetFlag(UnitFields.Flags, UnitFlags.Stunned);
|
||||
|
||||
player.SendMovementSetCollisionHeight(player.GetCollisionHeight(true));
|
||||
}
|
||||
|
||||
@@ -1335,6 +1342,12 @@ namespace Game.Entities
|
||||
}
|
||||
else
|
||||
player.ResummonPetTemporaryUnSummonedIfAny();
|
||||
|
||||
// if we have charmed npc, remove stun also
|
||||
Unit charm = player.GetCharm();
|
||||
if (charm)
|
||||
if (charm.GetTypeId() == TypeId.Unit && charm.HasFlag(UnitFields.Flags, UnitFlags.Stunned) && !charm.HasUnitState(UnitState.Stunned))
|
||||
charm.RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,7 +1358,7 @@ namespace Game.Entities
|
||||
return false;
|
||||
|
||||
m_vehicleKit = new Vehicle(this, vehInfo, creatureEntry);
|
||||
m_updateFlag |= UpdateFlag.Vehicle;
|
||||
m_updateFlag.Vehicle = true;
|
||||
m_unitTypeMask |= UnitTypeMask.Vehicle;
|
||||
|
||||
if (!loading)
|
||||
@@ -1366,7 +1379,7 @@ namespace Game.Entities
|
||||
|
||||
m_vehicleKit = null;
|
||||
|
||||
m_updateFlag &= ~UpdateFlag.Vehicle;
|
||||
m_updateFlag.Vehicle = false;
|
||||
m_unitTypeMask &= ~UnitTypeMask.Vehicle;
|
||||
RemoveFlag64(UnitFields.NpcFlags, NPCFlags.SpellClick | NPCFlags.PlayerVehicle);
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace Game.Entities
|
||||
{
|
||||
SetCritterGUID(minion.GetGUID());
|
||||
if (GetTypeId() == TypeId.Player)
|
||||
minion.SetGuidValue(UnitFields.BattlePetCompanionGuid, GetGuidValue(PlayerFields.SummonedBattlePetId));
|
||||
minion.SetGuidValue(UnitFields.BattlePetCompanionGuid, GetGuidValue(ActivePlayerFields.SummonedBattlePetId));
|
||||
}
|
||||
|
||||
// PvP, FFAPvP
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Game.Entities
|
||||
{
|
||||
if (IsTypeId(TypeId.Player))
|
||||
{
|
||||
float overrideSP = GetFloatValue(PlayerFields.OverrideSpellPowerByApPct);
|
||||
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
|
||||
if (overrideSP > 0.0f)
|
||||
return (int)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
|
||||
}
|
||||
@@ -190,7 +190,7 @@ namespace Game.Entities
|
||||
for (int i = 0; i < (int)SpellSchools.Max; ++i)
|
||||
{
|
||||
if (Convert.ToBoolean((int)spellProto.GetSchoolMask() & (1 << i)))
|
||||
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(PlayerFields.ModDamageDonePct + i));
|
||||
maxModDamagePercentSchool = Math.Max(maxModDamagePercentSchool, GetFloatValue(ActivePlayerFields.ModDamageDonePct + i));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -338,7 +338,7 @@ namespace Game.Entities
|
||||
{
|
||||
if (IsTypeId(TypeId.Player))
|
||||
{
|
||||
float overrideSP = GetFloatValue(PlayerFields.OverrideSpellPowerByApPct);
|
||||
float overrideSP = GetFloatValue(ActivePlayerFields.OverrideSpellPowerByApPct);
|
||||
if (overrideSP > 0.0f)
|
||||
return (uint)(MathFunctions.CalculatePct(GetTotalAttackPowerValue(WeaponAttackType.BaseAttack), overrideSP) + 0.5f);
|
||||
}
|
||||
@@ -503,7 +503,7 @@ namespace Game.Entities
|
||||
return 1.0f;
|
||||
|
||||
if (IsPlayer())
|
||||
return GetFloatValue(PlayerFields.ModHealingDonePct);
|
||||
return GetFloatValue(ActivePlayerFields.ModHealingDonePct);
|
||||
|
||||
float DoneTotalMod = 1.0f;
|
||||
|
||||
@@ -640,7 +640,7 @@ namespace Game.Entities
|
||||
crit_chance = 0.0f;
|
||||
// For other schools
|
||||
else if (IsTypeId(TypeId.Player))
|
||||
crit_chance = GetFloatValue(PlayerFields.CritPercentage);
|
||||
crit_chance = GetFloatValue(ActivePlayerFields.CritPercentage);
|
||||
else
|
||||
crit_chance = m_baseSpellCritChance;
|
||||
|
||||
@@ -1588,11 +1588,13 @@ namespace Game.Entities
|
||||
var schoolList = m_spellImmune[(int)SpellImmunity.School];
|
||||
foreach (var pair in schoolList)
|
||||
{
|
||||
if ((pair.Key & (uint)spellInfo.GetSchoolMask()) == 0)
|
||||
continue;
|
||||
|
||||
SpellInfo immuneSpellInfo = Global.SpellMgr.GetSpellInfo(pair.Value);
|
||||
if (Convert.ToBoolean(pair.Key & (uint)spellInfo.GetSchoolMask())
|
||||
&& !(immuneSpellInfo != null && immuneSpellInfo.IsPositive() && spellInfo.IsPositive() && IsFriendlyTo(caster))
|
||||
&& !spellInfo.CanPierceImmuneAura(immuneSpellInfo))
|
||||
return true;
|
||||
if (!(immuneSpellInfo != null && immuneSpellInfo.IsPositive() && spellInfo.IsPositive() && caster && IsFriendlyTo(caster)))
|
||||
if (!spellInfo.CanPierceImmuneAura(immuneSpellInfo))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -2234,29 +2236,13 @@ namespace Game.Entities
|
||||
|
||||
spellHealLog.TargetGUID = healInfo.GetTarget().GetGUID();
|
||||
spellHealLog.CasterGUID = healInfo.GetHealer().GetGUID();
|
||||
|
||||
spellHealLog.SpellID = healInfo.GetSpellInfo().Id;
|
||||
spellHealLog.Health = healInfo.GetHeal();
|
||||
spellHealLog.OriginalHeal = (int)healInfo.GetOriginalHeal();
|
||||
spellHealLog.OverHeal = healInfo.GetHeal() - healInfo.GetEffectiveHeal();
|
||||
spellHealLog.Absorbed = healInfo.GetAbsorb();
|
||||
|
||||
spellHealLog.Crit = critical;
|
||||
|
||||
// @todo: 6.x Has to be implemented
|
||||
/*
|
||||
var hasCritRollMade = spellHealLog.WriteBit("HasCritRollMade");
|
||||
var hasCritRollNeeded = spellHealLog.WriteBit("HasCritRollNeeded");
|
||||
var hasLogData = spellHealLog.WriteBit("HasLogData");
|
||||
|
||||
if (hasCritRollMade)
|
||||
packet.ReadSingle("CritRollMade");
|
||||
|
||||
if (hasCritRollNeeded)
|
||||
packet.ReadSingle("CritRollNeeded");
|
||||
|
||||
if (hasLogData)
|
||||
SpellParsers.ReadSpellCastLogData(packet);
|
||||
*/
|
||||
spellHealLog.LogData.Initialize(healInfo.GetTarget());
|
||||
SendCombatLogMessage(spellHealLog);
|
||||
}
|
||||
@@ -2411,6 +2397,7 @@ namespace Game.Entities
|
||||
damage = 0;
|
||||
|
||||
damageInfo.damage = (uint)damage;
|
||||
damageInfo.originalDamage = (uint)damage;
|
||||
DamageInfo dmgInfo = new DamageInfo(damageInfo, DamageEffectType.SpellDirect, WeaponAttackType.BaseAttack, ProcFlagsHit.None);
|
||||
CalcAbsorbResist(dmgInfo);
|
||||
damageInfo.absorb = dmgInfo.GetAbsorb();
|
||||
@@ -2456,6 +2443,7 @@ namespace Game.Entities
|
||||
packet.CastID = log.castId;
|
||||
packet.SpellID = (int)log.SpellId;
|
||||
packet.Damage = (int)log.damage;
|
||||
packet.OriginalDamage = (int)log.originalDamage;
|
||||
if (log.damage > log.preHitHealth)
|
||||
packet.Overkill = (int)(log.damage - log.preHitHealth);
|
||||
else
|
||||
@@ -2468,9 +2456,9 @@ namespace Game.Entities
|
||||
packet.Periodic = log.periodicLog;
|
||||
packet.Flags = (int)log.HitInfo;
|
||||
|
||||
SandboxScalingData sandboxScalingData = new SandboxScalingData();
|
||||
if (sandboxScalingData.GenerateDataForUnits(log.attacker, log.target))
|
||||
packet.SandboxScaling.Set(sandboxScalingData);
|
||||
ContentTuningParams contentTuningParams = new ContentTuningParams();
|
||||
if (contentTuningParams.GenerateDataForUnits(log.attacker, log.target))
|
||||
packet.ContentTuning.Set(contentTuningParams);
|
||||
|
||||
SendCombatLogMessage(packet);
|
||||
}
|
||||
@@ -2488,6 +2476,7 @@ namespace Game.Entities
|
||||
SpellPeriodicAuraLog.SpellLogEffect spellLogEffect = new SpellPeriodicAuraLog.SpellLogEffect();
|
||||
spellLogEffect.Effect = (uint)aura.GetAuraType();
|
||||
spellLogEffect.Amount = info.damage;
|
||||
spellLogEffect.OriginalDamage = (int)info.originalDamage;
|
||||
spellLogEffect.OverHealOrKill = (uint)info.overDamage;
|
||||
spellLogEffect.SchoolMaskOrPower = (uint)aura.GetSpellInfo().GetSchoolMask();
|
||||
spellLogEffect.AbsorbedOrAmplitude = info.absorb;
|
||||
@@ -2495,11 +2484,10 @@ namespace Game.Entities
|
||||
spellLogEffect.Crit = info.critical;
|
||||
// @todo: implement debug info
|
||||
|
||||
SandboxScalingData sandboxScalingData = new SandboxScalingData();
|
||||
ContentTuningParams contentTuningParams = new ContentTuningParams();
|
||||
Unit caster = Global.ObjAccessor.GetUnit(this, aura.GetCasterGUID());
|
||||
if (caster)
|
||||
if (sandboxScalingData.GenerateDataForUnits(caster, this))
|
||||
spellLogEffect.SandboxScaling.Set(sandboxScalingData);
|
||||
if (caster && contentTuningParams.GenerateDataForUnits(caster, this))
|
||||
spellLogEffect.ContentTuning.Set(contentTuningParams);
|
||||
|
||||
data.Effects.Add(spellLogEffect);
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Game.Entities
|
||||
|
||||
objectTypeId = TypeId.Unit;
|
||||
objectTypeMask |= TypeMask.Unit;
|
||||
m_updateFlag = UpdateFlag.Living;
|
||||
m_updateFlag.MovementUpdate = true;
|
||||
|
||||
m_modAttackSpeedPct = new float[] { 1.0f, 1.0f, 1.0f };
|
||||
m_deathState = DeathState.Alive;
|
||||
@@ -2076,9 +2076,9 @@ namespace Game.Entities
|
||||
{
|
||||
return (Race)GetByteValue(UnitFields.Bytes0, 0);
|
||||
}
|
||||
public long getRaceMask()
|
||||
public ulong getRaceMask()
|
||||
{
|
||||
return (1 << ((int)GetRace() - 1));
|
||||
return (1ul << ((int)GetRace() - 1));
|
||||
}
|
||||
public Class GetClass()
|
||||
{
|
||||
@@ -2093,13 +2093,15 @@ namespace Game.Entities
|
||||
return (Gender)GetByteValue(UnitFields.Bytes0, 3);
|
||||
}
|
||||
|
||||
public void SetNativeDisplayId(uint modelId)
|
||||
public void SetNativeDisplayId(uint displayId, float displayScale = 1f)
|
||||
{
|
||||
SetUInt32Value(UnitFields.NativeDisplayId, modelId);
|
||||
SetUInt32Value(UnitFields.NativeDisplayId, displayId);
|
||||
SetFloatValue(UnitFields.NativeXDisplayScale, displayScale);
|
||||
}
|
||||
public virtual void SetDisplayId(uint modelId)
|
||||
public virtual void SetDisplayId(uint modelId, float displayScale = 1f)
|
||||
{
|
||||
SetUInt32Value(UnitFields.DisplayId, modelId);
|
||||
SetFloatValue(UnitFields.DisplayScale, displayScale);
|
||||
// Set Gender by modelId
|
||||
CreatureModelInfo minfo = Global.ObjectMgr.GetCreatureModelInfo(modelId);
|
||||
if (minfo != null)
|
||||
@@ -2109,7 +2111,10 @@ namespace Game.Entities
|
||||
{
|
||||
return GetUInt32Value(UnitFields.NativeDisplayId);
|
||||
}
|
||||
|
||||
public float GetNativeDisplayScale()
|
||||
{
|
||||
return GetFloatValue(UnitFields.NativeXDisplayScale);
|
||||
}
|
||||
public virtual Unit GetOwner()
|
||||
{
|
||||
ObjectGuid ownerid = GetOwnerGUID();
|
||||
@@ -2570,7 +2575,7 @@ namespace Game.Entities
|
||||
{
|
||||
CreatureTemplate ci = Global.ObjectMgr.GetCreatureTemplate((uint)eff.GetMiscValue());
|
||||
if (ci != null)
|
||||
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci)))
|
||||
if (!IsDisallowedMountForm(eff.GetId(), ShapeShiftForm.None, ObjectManager.ChooseDisplayId(ci).CreatureDisplayID))
|
||||
handledAura = eff;
|
||||
}
|
||||
}
|
||||
@@ -2642,7 +2647,7 @@ namespace Game.Entities
|
||||
if (target == this)
|
||||
visibleFlag |= UpdateFieldFlags.Private;
|
||||
else if (IsTypeId(TypeId.Player))
|
||||
valCount = (int)PlayerFields.EndNotSelf;
|
||||
valCount = (int)PlayerFields.End;
|
||||
|
||||
UpdateMask updateMask = new UpdateMask(valCount);
|
||||
|
||||
@@ -2684,8 +2689,6 @@ namespace Game.Entities
|
||||
}
|
||||
// FIXME: Some values at server stored in float format but must be sent to client in public uint format
|
||||
else if ((index >= (int)UnitFields.NegStat && index < (int)UnitFields.NegStat + (int)Stats.Max) ||
|
||||
(index >= (int)UnitFields.ResistanceBuffModsPositive && index < ((int)UnitFields.ResistanceBuffModsPositive + (int)SpellSchools.Max)) ||
|
||||
(index >= (int)UnitFields.ResistanceBuffModsNegative && index < ((int)UnitFields.ResistanceBuffModsNegative + (int)SpellSchools.Max)) ||
|
||||
(index >= (int)UnitFields.PosStat && index < (int)UnitFields.PosStat + (int)Stats.Max))
|
||||
{
|
||||
fieldBuffer.WriteUInt32((uint)GetFloatValue(index));
|
||||
@@ -2727,7 +2730,7 @@ namespace Game.Entities
|
||||
|
||||
if (cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Trigger))
|
||||
if (target.IsGameMaster())
|
||||
displayId = cinfo.GetFirstVisibleModel();
|
||||
displayId = cinfo.GetFirstVisibleModel().CreatureDisplayID;
|
||||
}
|
||||
|
||||
fieldBuffer.WriteUInt32(displayId);
|
||||
|
||||
@@ -175,6 +175,11 @@ namespace Game.Entities
|
||||
// why we need to apply this? we can simple add immunities to slow mechanic in DB
|
||||
_me.ApplySpellImmune(0, SpellImmunity.State, AuraType.ModDecreaseSpeed, true);
|
||||
break;
|
||||
case 335: // Salvaged Chopper
|
||||
case 336: // Salvaged Siege Engine
|
||||
case 338: // Salvaged Demolisher
|
||||
_me.ApplySpellImmune(0, SpellImmunity.State, AuraType.ModDamagePercentTaken, false); // Battering Ram
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -342,6 +347,10 @@ namespace Game.Entities
|
||||
if (seat.Value.SeatInfo.CanEnterOrExit() && ++UsableSeatNum != 0)
|
||||
_me.SetFlag64(UnitFields.NpcFlags, (_me.IsTypeId(TypeId.Player) ? NPCFlags.PlayerVehicle : NPCFlags.SpellClick));
|
||||
|
||||
// Enable gravity for passenger when he did not have it active before entering the vehicle
|
||||
if (seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.DisableGravity) && !seat.Value.Passenger.IsGravityDisabled)
|
||||
unit.SetDisableGravity(false);
|
||||
|
||||
// Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle
|
||||
if (seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.PassengerNotSelectable) && !seat.Value.Passenger.IsUnselectable)
|
||||
unit.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
@@ -552,6 +561,7 @@ namespace Game.Entities
|
||||
Passenger.SetVehicle(Target);
|
||||
Seat.Value.Passenger.Guid = Passenger.GetGUID();
|
||||
Seat.Value.Passenger.IsUnselectable = Passenger.HasFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
Seat.Value.Passenger.IsGravityDisabled = Passenger.HasUnitMovementFlag(MovementFlag.DisableGravity);
|
||||
if (Seat.Value.SeatInfo.CanEnterOrExit())
|
||||
{
|
||||
Cypher.Assert(Target.UsableSeatNum != 0);
|
||||
@@ -585,6 +595,9 @@ namespace Game.Entities
|
||||
player.UnsummonPetTemporaryIfAny();
|
||||
}
|
||||
|
||||
if (veSeat.Flags.HasAnyFlag(VehicleSeatFlags.DisableGravity))
|
||||
Passenger.SetDisableGravity(true);
|
||||
|
||||
if (Seat.Value.SeatInfo.Flags.HasAnyFlag(VehicleSeatFlags.PassengerNotSelectable))
|
||||
Passenger.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
|
||||
@@ -657,11 +670,13 @@ namespace Game.Entities
|
||||
{
|
||||
public ObjectGuid Guid;
|
||||
public bool IsUnselectable;
|
||||
public bool IsGravityDisabled;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Guid = ObjectGuid.Empty;
|
||||
IsUnselectable = false;
|
||||
IsGravityDisabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -688,7 +688,7 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
mGameEventNPCFlags[event_id].Add(Tuple.Create(guid, npcflag));
|
||||
mGameEventNPCFlags[event_id].Add((guid, npcflag));
|
||||
|
||||
++count;
|
||||
}
|
||||
@@ -762,9 +762,9 @@ namespace Game
|
||||
var flist = mGameEventNPCFlags[event_id];
|
||||
foreach (var pair in flist)
|
||||
{
|
||||
if (pair.Item1 == guid)
|
||||
if (pair.guid == guid)
|
||||
{
|
||||
event_npc_flag = pair.Item2;
|
||||
event_npc_flag = pair.npcflag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -883,8 +883,8 @@ namespace Game
|
||||
foreach (var id in m_ActiveEvents)
|
||||
{
|
||||
foreach (var pair in mGameEventNPCFlags[id])
|
||||
if (pair.Item1 == guid)
|
||||
mask |= pair.Item2;
|
||||
if (pair.guid == guid)
|
||||
mask |= pair.npcflag;
|
||||
}
|
||||
|
||||
return mask;
|
||||
@@ -916,7 +916,7 @@ namespace Game
|
||||
mGameEventGameObjectQuests = new List<Tuple<uint, uint>>[maxEventId];
|
||||
mGameEventVendors = new Dictionary<uint, VendorItem>[maxEventId];
|
||||
mGameEventBattlegroundHolidays = new uint[maxEventId];
|
||||
mGameEventNPCFlags = new List<Tuple<ulong, ulong>>[maxEventId];
|
||||
mGameEventNPCFlags = new List<(ulong guid, ulong npcflag)>[maxEventId];
|
||||
mGameEventModelEquip = new List<Tuple<ulong, ModelEquip>>[maxEventId];
|
||||
for (var i = 0; i < maxEventId; ++i)
|
||||
{
|
||||
@@ -924,7 +924,7 @@ namespace Game
|
||||
mGameEventCreatureQuests[i] = new List<Tuple<uint, uint>>();
|
||||
mGameEventGameObjectQuests[i] = new List<Tuple<uint, uint>>();
|
||||
mGameEventVendors[i] = new Dictionary<uint, VendorItem>();
|
||||
mGameEventNPCFlags[i] = new List<Tuple<ulong, ulong>>();
|
||||
mGameEventNPCFlags[i] = new List<(ulong guid, ulong npcflag)>();
|
||||
mGameEventModelEquip[i] = new List<Tuple<ulong, ModelEquip>>();
|
||||
}
|
||||
}
|
||||
@@ -1100,9 +1100,9 @@ namespace Game
|
||||
foreach (var pair in mGameEventNPCFlags[event_id])
|
||||
{
|
||||
// get the creature data from the low guid to get the entry, to be able to find out the whole guid
|
||||
CreatureData data = Global.ObjectMgr.GetCreatureData(pair.Item1);
|
||||
CreatureData data = Global.ObjectMgr.GetCreatureData(pair.guid);
|
||||
if (data != null)
|
||||
creaturesByMap.Add(data.mapid, pair.Item1);
|
||||
creaturesByMap.Add(data.mapid, pair.guid);
|
||||
}
|
||||
|
||||
foreach (var key in creaturesByMap.Keys)
|
||||
@@ -1607,7 +1607,7 @@ namespace Game
|
||||
GameEventData[] mGameEvent;
|
||||
uint[] mGameEventBattlegroundHolidays;
|
||||
Dictionary<uint, GameEventQuestToEventConditionNum> mQuestToEventConditions = new Dictionary<uint, GameEventQuestToEventConditionNum>();
|
||||
List<Tuple<ulong, ulong>>[] mGameEventNPCFlags;
|
||||
List<(ulong guid, ulong npcflag)>[] mGameEventNPCFlags;
|
||||
List<ushort> m_ActiveEvents = new List<ushort>();
|
||||
Dictionary<uint, ushort> _questToEventLinks = new Dictionary<uint, ushort>();
|
||||
bool isSystemInit;
|
||||
|
||||
@@ -48,29 +48,36 @@ namespace Game
|
||||
lang_description = new LanguageDesc[]
|
||||
{
|
||||
new LanguageDesc(Language.Addon, 0, 0 ),
|
||||
new LanguageDesc(Language.AddonLogged, 0, 0 ),
|
||||
new LanguageDesc(Language.Universal, 0, 0 ),
|
||||
new LanguageDesc(Language.Orcish, 669, SkillType.LangOrcish ),
|
||||
new LanguageDesc(Language.Darnassian, 671, SkillType.LangDarnassian ),
|
||||
new LanguageDesc(Language.Taurahe, 670, SkillType.LangTaurahe ),
|
||||
new LanguageDesc(Language.Dwarvish, 672, SkillType.LangDwarven ),
|
||||
new LanguageDesc(Language.Common, 668, SkillType.LangCommon ),
|
||||
new LanguageDesc(Language.Demonic, 815, SkillType.LangDemonTongue ),
|
||||
new LanguageDesc(Language.Titan, 816, SkillType.LangTitan ),
|
||||
new LanguageDesc(Language.Thalassian, 813, SkillType.LangThalassian ),
|
||||
new LanguageDesc(Language.Draconic, 814, SkillType.LangDraconic ),
|
||||
new LanguageDesc(Language.Kalimag, 817, SkillType.LangOldTongue ),
|
||||
new LanguageDesc(Language.Gnomish, 7340, SkillType.LangGnomish ),
|
||||
new LanguageDesc(Language.Troll, 7341, SkillType.LangTroll ),
|
||||
new LanguageDesc(Language.Gutterspeak, 17737, SkillType.LangForsaken ),
|
||||
new LanguageDesc(Language.Draenei, 29932, SkillType.LangDraenei ),
|
||||
new LanguageDesc(Language.Zombie, 0, 0 ),
|
||||
new LanguageDesc(Language.GnomishBinary, 0, 0 ),
|
||||
new LanguageDesc(Language.GoblinBinary, 0, 0 ),
|
||||
new LanguageDesc(Language.Worgen, 69270, SkillType.LangGilnean ),
|
||||
new LanguageDesc(Language.Goblin, 69269, SkillType.LangGoblin ),
|
||||
new LanguageDesc(Language.PandarenNeutral, 108127, SkillType.LangPandarenNeutral ),
|
||||
new LanguageDesc(Language.PandarenAlliance, 108130, SkillType.LangPandarenAlliance ),
|
||||
new LanguageDesc(Language.PandarenHorde, 108131, SkillType.LangPandarenHorde ),
|
||||
new LanguageDesc(Language.Orcish, 669, SkillType.LanguageOrcish ),
|
||||
new LanguageDesc(Language.Darnassian, 671, SkillType.LanguageDarnassian ),
|
||||
new LanguageDesc(Language.Taurahe, 670, SkillType.LanguageTaurahe ),
|
||||
new LanguageDesc(Language.Dwarvish, 672, SkillType.LanguageDwarven ),
|
||||
new LanguageDesc(Language.Common, 668, SkillType.LanguageCommon ),
|
||||
new LanguageDesc(Language.Demonic, 815, SkillType.LanguageDemonTongue ),
|
||||
new LanguageDesc(Language.Titan, 816, SkillType.LanguageTitan ),
|
||||
new LanguageDesc(Language.Thalassian, 813, SkillType.LanguageThalassian ),
|
||||
new LanguageDesc(Language.Draconic, 814, SkillType.LanguageDraconic ),
|
||||
new LanguageDesc(Language.Kalimag, 265462, SkillType.LanguageOldTongue ),
|
||||
new LanguageDesc(Language.Gnomish, 7340, SkillType.LanguageGnomish ),
|
||||
new LanguageDesc(Language.Troll, 7341, SkillType.LanguageTroll ),
|
||||
new LanguageDesc(Language.Gutterspeak, 17737, SkillType.LanguageForsaken ),
|
||||
new LanguageDesc(Language.Draenei, 29932, SkillType.LanguageDraenei ),
|
||||
new LanguageDesc(Language.Zombie, 265467, 0 ),
|
||||
new LanguageDesc(Language.GnomishBinary, 265460, 0 ),
|
||||
new LanguageDesc(Language.GoblinBinary, 265461, 0 ),
|
||||
new LanguageDesc(Language.Worgen, 69270, SkillType.LanguageGilnean ),
|
||||
new LanguageDesc(Language.Goblin, 69269, SkillType.LanguageGoblin ),
|
||||
new LanguageDesc(Language.PandarenNeutral, 108127, SkillType.LanguagePandarenNeutral ),
|
||||
new LanguageDesc(Language.PandarenAlliance, 108130, 0 ),
|
||||
new LanguageDesc(Language.PandarenHorde, 108131, 0 ),
|
||||
new LanguageDesc(Language.Sprite, 265466, 0 ),
|
||||
new LanguageDesc(Language.ShathYar, 265465, 0 ),
|
||||
new LanguageDesc(Language.Nerglish, 265464, 0 ),
|
||||
new LanguageDesc(Language.Moonkin, 265463, 0 ),
|
||||
new LanguageDesc(Language.Shalassian, 262439, SkillType.LanguageShalassian ),
|
||||
new LanguageDesc(Language.Thalassian2, 262454, SkillType.LanguageThalassian2 )
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,14 +146,22 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
public static uint ChooseDisplayId(CreatureTemplate cinfo, CreatureData data = null)
|
||||
public static CreatureModel ChooseDisplayId(CreatureTemplate cinfo, CreatureData data = null)
|
||||
{
|
||||
// Load creature model (display id)
|
||||
if (data != null && data.displayid != 0)
|
||||
return data.displayid;
|
||||
{
|
||||
CreatureModel model = cinfo.GetModelWithDisplayId(data.displayid);
|
||||
if (model != null)
|
||||
return model;
|
||||
}
|
||||
|
||||
if (!cinfo.FlagsExtra.HasAnyFlag(CreatureFlagsExtra.Trigger))
|
||||
return cinfo.GetRandomValidModelId();
|
||||
{
|
||||
CreatureModel model = cinfo.GetRandomValidModel();
|
||||
if (model != null)
|
||||
return model;
|
||||
}
|
||||
|
||||
// Triggers by default receive the invisible model
|
||||
return cinfo.GetFirstInvisibleModel();
|
||||
@@ -1731,23 +1746,24 @@ namespace Game
|
||||
{
|
||||
var time = Time.GetMSTime();
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
SQLResult result = DB.World.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, " +
|
||||
//9 10 11 12 13 14 15 16 17 18 19 20
|
||||
"modelid4, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, " +
|
||||
//21 22 23 24 25 26 27 28 29 30 31
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
SQLResult result = DB.World.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, " +
|
||||
//9 10 11 12 13 14 15 16
|
||||
"TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, " +
|
||||
//17 18 19 20 21 22 23 24 25 26 27
|
||||
"faction, npcflag, speed_walk, speed_run, scale, rank, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, " +
|
||||
//32 33 34 35 36 37 38 39
|
||||
//28 29 30 31 32 33 34 35
|
||||
"unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, " +
|
||||
// 40 41 42 43 44 45 46 47 48 49 50
|
||||
//36 37 38 39 40 41 42 43 44 45 46
|
||||
"type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, " +
|
||||
//51 52 53 54 55 56 57 58 59 60 61 62 63
|
||||
//47 48 49 50 51 52 53 54 55 56 57 58 59
|
||||
"spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, " +
|
||||
//64 65 66 67 68 69 70 71 72
|
||||
//60 61 62 63 64 65 66 67 68
|
||||
"InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, " +
|
||||
//73 74 75 76 77 78
|
||||
//69 70 71 72 73 74
|
||||
"RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template");
|
||||
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, "Loaded 0 creatures. DB table `creature_template` is empty.");
|
||||
@@ -1759,6 +1775,9 @@ namespace Game
|
||||
LoadCreatureTemplate(result.GetFields());
|
||||
} while (result.NextRow());
|
||||
|
||||
// We load the creature models after loading but before checking
|
||||
LoadCreatureTemplateModels();
|
||||
|
||||
// Checking needs to be done after loading because of the difficulty self referencing
|
||||
foreach (var template in creatureTemplateStorage.Values)
|
||||
CheckCreatureTemplate(template);
|
||||
@@ -1778,75 +1797,119 @@ namespace Game
|
||||
for (var i = 0; i < 2; ++i)
|
||||
creature.KillCredit[i] = fields.Read<uint>(4 + i);
|
||||
|
||||
creature.ModelId1 = fields.Read<uint>(6);
|
||||
creature.ModelId2 = fields.Read<uint>(7);
|
||||
creature.ModelId3 = fields.Read<uint>(8);
|
||||
creature.ModelId4 = fields.Read<uint>(9);
|
||||
creature.Name = fields.Read<string>(10);
|
||||
creature.FemaleName = fields.Read<string>(11);
|
||||
creature.SubName = fields.Read<string>(12);
|
||||
creature.TitleAlt = fields.Read<string>(13);
|
||||
creature.IconName = fields.Read<string>(14);
|
||||
creature.GossipMenuId = fields.Read<uint>(15);
|
||||
creature.Minlevel = fields.Read<short>(16);
|
||||
creature.Maxlevel = fields.Read<short>(17);
|
||||
creature.HealthScalingExpansion = fields.Read<int>(18);
|
||||
creature.RequiredExpansion = fields.Read<uint>(19);
|
||||
creature.VignetteID = fields.Read<uint>(20);
|
||||
creature.Faction = fields.Read<uint>(21);
|
||||
creature.Npcflag = (NPCFlags)fields.Read<uint>(22);
|
||||
creature.SpeedWalk = fields.Read<float>(23);
|
||||
creature.SpeedRun = fields.Read<float>(24);
|
||||
creature.Scale = fields.Read<float>(25);
|
||||
creature.Rank = (CreatureEliteType)fields.Read<uint>(26);
|
||||
creature.DmgSchool = fields.Read<uint>(27);
|
||||
creature.BaseAttackTime = fields.Read<uint>(28);
|
||||
creature.RangeAttackTime = fields.Read<uint>(29);
|
||||
creature.BaseVariance = fields.Read<float>(30);
|
||||
creature.RangeVariance = fields.Read<float>(31);
|
||||
creature.UnitClass = fields.Read<uint>(32);
|
||||
creature.UnitFlags = (UnitFlags)fields.Read<uint>(33);
|
||||
creature.UnitFlags2 = fields.Read<uint>(34);
|
||||
creature.UnitFlags3 = fields.Read<uint>(35);
|
||||
creature.DynamicFlags = fields.Read<uint>(36);
|
||||
creature.Family = (CreatureFamily)fields.Read<byte>(37);
|
||||
creature.TrainerClass = (Class)fields.Read<byte>(38);
|
||||
creature.CreatureType = (CreatureType)fields.Read<uint>(39);
|
||||
creature.TypeFlags = (CreatureTypeFlags)fields.Read<uint>(40);
|
||||
creature.TypeFlags2 = fields.Read<uint>(41);
|
||||
creature.LootId = fields.Read<uint>(42);
|
||||
creature.PickPocketId = fields.Read<uint>(43);
|
||||
creature.SkinLootId = fields.Read<uint>(44);
|
||||
creature.Name = fields.Read<string>(6);
|
||||
creature.FemaleName = fields.Read<string>(7);
|
||||
creature.SubName = fields.Read<string>(8);
|
||||
creature.TitleAlt = fields.Read<string>(9);
|
||||
creature.IconName = fields.Read<string>(10);
|
||||
creature.GossipMenuId = fields.Read<uint>(11);
|
||||
creature.Minlevel = fields.Read<short>(12);
|
||||
creature.Maxlevel = fields.Read<short>(13);
|
||||
creature.HealthScalingExpansion = fields.Read<int>(14);
|
||||
creature.RequiredExpansion = fields.Read<uint>(15);
|
||||
creature.VignetteID = fields.Read<uint>(16);
|
||||
creature.Faction = fields.Read<uint>(17);
|
||||
creature.Npcflag = (NPCFlags)fields.Read<uint>(18);
|
||||
creature.SpeedWalk = fields.Read<float>(19);
|
||||
creature.SpeedRun = fields.Read<float>(20);
|
||||
creature.Scale = fields.Read<float>(21);
|
||||
creature.Rank = (CreatureEliteType)fields.Read<uint>(22);
|
||||
creature.DmgSchool = fields.Read<uint>(23);
|
||||
creature.BaseAttackTime = fields.Read<uint>(24);
|
||||
creature.RangeAttackTime = fields.Read<uint>(25);
|
||||
creature.BaseVariance = fields.Read<float>(26);
|
||||
creature.RangeVariance = fields.Read<float>(27);
|
||||
creature.UnitClass = fields.Read<uint>(28);
|
||||
creature.UnitFlags = (UnitFlags)fields.Read<uint>(29);
|
||||
creature.UnitFlags2 = fields.Read<uint>(30);
|
||||
creature.UnitFlags3 = fields.Read<uint>(31);
|
||||
creature.DynamicFlags = fields.Read<uint>(32);
|
||||
creature.Family = (CreatureFamily)fields.Read<byte>(33);
|
||||
creature.TrainerClass = (Class)fields.Read<byte>(34);
|
||||
creature.CreatureType = (CreatureType)fields.Read<uint>(35);
|
||||
creature.TypeFlags = (CreatureTypeFlags)fields.Read<uint>(36);
|
||||
creature.TypeFlags2 = fields.Read<uint>(37);
|
||||
creature.LootId = fields.Read<uint>(38);
|
||||
creature.PickPocketId = fields.Read<uint>(39);
|
||||
creature.SkinLootId = fields.Read<uint>(40);
|
||||
|
||||
for (var i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
|
||||
creature.Resistance[i] = fields.Read<int>(45 + i - 1);
|
||||
creature.Resistance[i] = fields.Read<int>(41 + i - 1);
|
||||
|
||||
for (var i = 0; i < SharedConst.MaxCreatureSpells; ++i)
|
||||
creature.Spells[i] = fields.Read<uint>(51 + i);
|
||||
creature.Spells[i] = fields.Read<uint>(47 + i);
|
||||
|
||||
creature.VehicleId = fields.Read<uint>(59);
|
||||
creature.MinGold = fields.Read<uint>(60);
|
||||
creature.MaxGold = fields.Read<uint>(61);
|
||||
creature.AIName = fields.Read<string>(62);
|
||||
creature.MovementType = fields.Read<uint>(63);
|
||||
creature.InhabitType = (InhabitType)fields.Read<uint>(64);
|
||||
creature.HoverHeight = fields.Read<float>(65);
|
||||
creature.ModHealth = fields.Read<float>(66);
|
||||
creature.ModHealthExtra = fields.Read<float>(67);
|
||||
creature.ModMana = fields.Read<float>(68);
|
||||
creature.ModManaExtra = fields.Read<float>(69);
|
||||
creature.ModArmor = fields.Read<float>(70);
|
||||
creature.ModDamage = fields.Read<float>(71);
|
||||
creature.ModExperience = fields.Read<float>(72);
|
||||
creature.RacialLeader = fields.Read<bool>(73);
|
||||
creature.MovementId = fields.Read<uint>(74);
|
||||
creature.RegenHealth = fields.Read<bool>(75);
|
||||
creature.MechanicImmuneMask = fields.Read<uint>(76);
|
||||
creature.FlagsExtra = (CreatureFlagsExtra)fields.Read<uint>(77);
|
||||
creature.ScriptID = GetScriptId(fields.Read<string>(78));
|
||||
creature.VehicleId = fields.Read<uint>(55);
|
||||
creature.MinGold = fields.Read<uint>(56);
|
||||
creature.MaxGold = fields.Read<uint>(57);
|
||||
creature.AIName = fields.Read<string>(58);
|
||||
creature.MovementType = fields.Read<uint>(59);
|
||||
creature.InhabitType = (InhabitType)fields.Read<uint>(60);
|
||||
creature.HoverHeight = fields.Read<float>(61);
|
||||
creature.ModHealth = fields.Read<float>(62);
|
||||
creature.ModHealthExtra = fields.Read<float>(63);
|
||||
creature.ModMana = fields.Read<float>(64);
|
||||
creature.ModManaExtra = fields.Read<float>(65);
|
||||
creature.ModArmor = fields.Read<float>(66);
|
||||
creature.ModDamage = fields.Read<float>(67);
|
||||
creature.ModExperience = fields.Read<float>(68);
|
||||
creature.RacialLeader = fields.Read<bool>(69);
|
||||
creature.MovementId = fields.Read<uint>(70);
|
||||
creature.RegenHealth = fields.Read<bool>(71);
|
||||
creature.MechanicImmuneMask = fields.Read<uint>(72);
|
||||
creature.FlagsExtra = (CreatureFlagsExtra)fields.Read<uint>(73);
|
||||
creature.ScriptID = GetScriptId(fields.Read<string>(74));
|
||||
|
||||
creatureTemplateStorage.Add(entry, creature);
|
||||
}
|
||||
|
||||
void LoadCreatureTemplateModels()
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
// 0 1 2 3
|
||||
SQLResult result = DB.World.Query("SELECT CreatureID, CreatureDisplayID, DisplayScale, Probability FROM creature_template_model ORDER BY Idx ASC");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 creature template model definitions. DB table `creature_template_model` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint creatureId = result.Read<uint>(0);
|
||||
uint creatureDisplayId = result.Read<uint>(1);
|
||||
float displayScale = result.Read<float>(2);
|
||||
float probability = result.Read<float>(3);
|
||||
|
||||
CreatureTemplate cInfo = GetCreatureTemplate(creatureId);
|
||||
if (cInfo == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Creature template (Entry: {creatureId}) does not exist but has a record in `creature_template_model`");
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatureDisplayInfoRecord displayEntry = CliDB.CreatureDisplayInfoStorage.LookupByKey(creatureDisplayId);
|
||||
if (displayEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Creature (Entry: {creatureId}) lists non-existing CreatureDisplayID id ({creatureDisplayId}), this can crash the client.");
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(creatureDisplayId);
|
||||
if (modelInfo == null)
|
||||
Log.outError(LogFilter.Sql, $"No model data exist for `CreatureDisplayID` = {creatureDisplayId} listed by creature (Entry: {creatureId}).");
|
||||
|
||||
if (displayScale <= 0.0f)
|
||||
displayScale = 1.0f;
|
||||
|
||||
cInfo.Models.Add(new CreatureModel(creatureDisplayId, displayScale, probability));
|
||||
++count;
|
||||
}
|
||||
while (result.NextRow());
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} creature template models in {Time.GetMSTimeDiffToNow(oldMSTime)} ms");
|
||||
}
|
||||
public void LoadCreatureTemplateAddons()
|
||||
{
|
||||
var time = Time.GetMSTime();
|
||||
@@ -2183,8 +2246,8 @@ namespace Game
|
||||
var time = Time.GetMSTime();
|
||||
|
||||
creatureBaseStatsStorage.Clear();
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
SQLResult result = DB.World.Query("SELECT level, class, basemana, basearmor, attackpower, rangedattackpower, damage_base, damage_exp1, damage_exp2, damage_exp3, damage_exp4, damage_exp5 FROM creature_classlevelstats");
|
||||
// 0 1 2 3 4 5
|
||||
SQLResult result = DB.World.Query("SELECT level, class, basemana, basearmor, attackpower, rangedattackpower FROM creature_classlevelstats");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
@@ -2509,75 +2572,6 @@ namespace Game
|
||||
cInfo.Faction = 35;
|
||||
}
|
||||
|
||||
// used later for scale
|
||||
CreatureDisplayInfoRecord displayScaleEntry = null;
|
||||
if (cInfo.ModelId1 != 0)
|
||||
{
|
||||
CreatureDisplayInfoRecord displayEntry = CliDB.CreatureDisplayInfoStorage.LookupByKey(cInfo.ModelId1);
|
||||
if (displayEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) lists non-existing Modelid1 id ({1}), this can crash the client.", cInfo.Entry, cInfo.ModelId1);
|
||||
cInfo.ModelId1 = 0;
|
||||
}
|
||||
else
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(cInfo.ModelId1);
|
||||
if (modelInfo == null)
|
||||
Log.outError(LogFilter.Sql, "No model data exist for `Modelid1` = {0} listed by creature (Entry: {1}).", cInfo.ModelId1, cInfo.Entry);
|
||||
}
|
||||
|
||||
if (cInfo.ModelId2 != 0)
|
||||
{
|
||||
CreatureDisplayInfoRecord displayEntry = CliDB.CreatureDisplayInfoStorage.LookupByKey(cInfo.ModelId2);
|
||||
if (displayEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) lists non-existing Modelid2 id ({1}), this can crash the client.", cInfo.Entry, cInfo.ModelId2);
|
||||
cInfo.ModelId2 = 0;
|
||||
}
|
||||
else if (displayScaleEntry == null)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(cInfo.ModelId2);
|
||||
if (modelInfo == null)
|
||||
Log.outError(LogFilter.Sql, "No model data exist for `Modelid2` = {0} listed by creature (Entry: {1}).", cInfo.ModelId2, cInfo.Entry);
|
||||
}
|
||||
|
||||
if (cInfo.ModelId3 != 0)
|
||||
{
|
||||
CreatureDisplayInfoRecord displayEntry = CliDB.CreatureDisplayInfoStorage.LookupByKey(cInfo.ModelId3);
|
||||
if (displayEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) lists non-existing Modelid3 id ({1}), this can crash the client.", cInfo.Entry, cInfo.ModelId3);
|
||||
cInfo.ModelId3 = 0;
|
||||
}
|
||||
else if (displayScaleEntry == null)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(cInfo.ModelId3);
|
||||
if (modelInfo == null)
|
||||
Log.outError(LogFilter.Sql, "No model data exist for `Modelid3` = {0} listed by creature (Entry: {1}).", cInfo.ModelId3, cInfo.Entry);
|
||||
}
|
||||
|
||||
if (cInfo.ModelId4 != 0)
|
||||
{
|
||||
CreatureDisplayInfoRecord displayEntry = CliDB.CreatureDisplayInfoStorage.LookupByKey(cInfo.ModelId4);
|
||||
if (displayEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) lists non-existing Modelid4 id ({1}), this can crash the client.", cInfo.Entry, cInfo.ModelId4);
|
||||
cInfo.ModelId4 = 0;
|
||||
}
|
||||
else if (displayScaleEntry == null)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(cInfo.ModelId4);
|
||||
if (modelInfo == null)
|
||||
Log.outError(LogFilter.Sql, "No model data exist for `Modelid4` = {0} listed by creature (Entry: {1}).", cInfo.ModelId4, cInfo.Entry);
|
||||
}
|
||||
|
||||
if (displayScaleEntry == null)
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo.Entry);
|
||||
|
||||
for (int k = 0; k < SharedConst.MaxCreatureKillCredit; ++k)
|
||||
{
|
||||
if (cInfo.KillCredit[k] != 0)
|
||||
@@ -2590,6 +2584,11 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
if (cInfo.Models.Empty())
|
||||
Log.outError(LogFilter.Sql, $"Creature (Entry: {cInfo.Entry}) does not have any existing display id in creature_template_model.");
|
||||
else if (cInfo.Models.Sum(p => p.Probability) <= 0.0f)
|
||||
Log.outError(LogFilter.Sql, $"Creature (Entry: {cInfo.Entry}) has zero total chance for all models in creature_template_model.");
|
||||
|
||||
if (cInfo.UnitClass == 0 || ((1 << ((int)cInfo.UnitClass - 1)) & (int)Class.ClassMaskAllCreatures) == 0)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid unit_class ({1}) in creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo.Entry, cInfo.UnitClass);
|
||||
@@ -2669,15 +2668,6 @@ namespace Game
|
||||
cInfo.MovementType = (uint)MovementGeneratorType.Idle;
|
||||
}
|
||||
|
||||
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
|
||||
if (cInfo.Scale <= 0.0f)
|
||||
{
|
||||
if (displayScaleEntry != null)
|
||||
cInfo.Scale = displayScaleEntry.CreatureModelScale;
|
||||
else
|
||||
cInfo.Scale = 1.0f;
|
||||
}
|
||||
|
||||
if (cInfo.HealthScalingExpansion < (int)Expansion.LevelCurrent || cInfo.HealthScalingExpansion > ((int)Expansion.Max - 1))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `creature_template` lists creature (Id: {0}) with invalid `HealthScalingExpansion` {1}. Ignored and set to 0.", cInfo.Entry, cInfo.HealthScalingExpansion);
|
||||
@@ -3015,17 +3005,6 @@ namespace Game
|
||||
if (!allReqValid)
|
||||
continue;
|
||||
|
||||
spell.LearnedSpellId = spell.SpellId;
|
||||
foreach (SpellEffectInfo spellEffect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
|
||||
{
|
||||
if (spellEffect != null && spellEffect.IsEffect(SpellEffectName.LearnSpell))
|
||||
{
|
||||
Cypher.Assert(spell.LearnedSpellId == spell.SpellId, $"Only one learned spell is currently supported - spell {spell.SpellId} already teaches {spell.LearnedSpellId} but it tried to overwrite it with {spellEffect.TriggerSpell}");
|
||||
spell.LearnedSpellId = spellEffect.TriggerSpell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spellsByTrainer.Add(trainerId, spell);
|
||||
|
||||
} while (trainerSpellsResult.NextRow());
|
||||
@@ -3286,7 +3265,7 @@ namespace Game
|
||||
data.curhealth = result.Read<uint>(12);
|
||||
data.curmana = result.Read<uint>(13);
|
||||
data.movementType = result.Read<byte>(14);
|
||||
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(15), "creature", guid, data.mapid, spawnMasks[data.mapid]);
|
||||
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(15), "creature", guid, data.mapid, spawnMasks.LookupByKey(data.mapid));
|
||||
short gameEvent = result.Read<short>(16);
|
||||
uint PoolId = result.Read<uint>(17);
|
||||
data.npcflag = result.Read<ulong>(18);
|
||||
@@ -3625,9 +3604,9 @@ namespace Game
|
||||
|
||||
return new DefaultCreatureBaseStats();
|
||||
}
|
||||
public CreatureModelInfo GetCreatureModelRandomGender(ref uint displayID)
|
||||
public CreatureModelInfo GetCreatureModelRandomGender(ref CreatureModel model, CreatureTemplate creatureTemplate)
|
||||
{
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(displayID);
|
||||
CreatureModelInfo modelInfo = GetCreatureModelInfo(model.CreatureDisplayID);
|
||||
if (modelInfo == null)
|
||||
return null;
|
||||
|
||||
@@ -3636,11 +3615,21 @@ namespace Game
|
||||
{
|
||||
CreatureModelInfo minfotmp = GetCreatureModelInfo(modelInfo.DisplayIdOtherGender);
|
||||
if (minfotmp == null)
|
||||
Log.outError(LogFilter.Sql, "Model (Entry: {0}) has modelidothergender {1} not found in table `creaturemodelinfo`. ", displayID, modelInfo.DisplayIdOtherGender);
|
||||
Log.outError(LogFilter.Sql, $"Model (Entry: {model.CreatureDisplayID}) has modelidothergender {modelInfo.DisplayIdOtherGender} not found in table `creaturemodelinfo`. ");
|
||||
else
|
||||
{
|
||||
// DisplayID changed
|
||||
displayID = modelInfo.DisplayIdOtherGender;
|
||||
model.CreatureDisplayID = modelInfo.DisplayIdOtherGender;
|
||||
if (creatureTemplate != null)
|
||||
{
|
||||
var creatureModel = creatureTemplate.Models.Find(templateModel =>
|
||||
{
|
||||
return templateModel.CreatureDisplayID == modelInfo.DisplayIdOtherGender;
|
||||
});
|
||||
|
||||
if (creatureModel != null)
|
||||
model = creatureModel;
|
||||
}
|
||||
return minfotmp;
|
||||
}
|
||||
}
|
||||
@@ -3691,8 +3680,8 @@ namespace Game
|
||||
"Data0, Data1, Data2, Data3, Data4, Data5, Data6, Data7, Data8, Data9, Data10, Data11, Data12, " +
|
||||
//21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
||||
"Data13, Data14, Data15, Data16, Data17, Data18, Data19, Data20, Data21, Data22, Data23, Data24, Data25, Data26, Data27, Data28, " +
|
||||
//37 38 39 40 41 42 43
|
||||
"Data29, Data30, Data31, Data32, RequiredLevel, AIName, ScriptName FROM gameobject_template");
|
||||
//37 38 39 40 41 42 44 44
|
||||
"Data29, Data30, Data31, Data32 Data33, RequiredLevel, AIName, ScriptName FROM gameobject_template");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
@@ -3725,9 +3714,9 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
got.RequiredLevel = result.Read<int>(41);
|
||||
got.AIName = result.Read<string>(42);
|
||||
got.ScriptId = Global.ObjectMgr.GetScriptId(result.Read<string>(43));
|
||||
got.RequiredLevel = result.Read<int>(42);
|
||||
got.AIName = result.Read<string>(43);
|
||||
got.ScriptId = Global.ObjectMgr.GetScriptId(result.Read<string>(44));
|
||||
|
||||
switch (got.type)
|
||||
{
|
||||
@@ -4026,7 +4015,7 @@ namespace Game
|
||||
}
|
||||
data.go_state = (GameObjectState)gostate;
|
||||
|
||||
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(14), "gameobject", guid, data.mapid, spawnMasks[data.mapid]);
|
||||
data.spawnDifficulties = ParseSpawnDifficulties(result.Read<string>(14), "gameobject", guid, data.mapid, spawnMasks.LookupByKey(data.mapid));
|
||||
if (data.spawnDifficulties.Empty())
|
||||
{
|
||||
Log.outError(LogFilter.Sql, $"Table `creature` has creature (GUID: {guid}) that is not spawned in any difficulty, skipped.");
|
||||
@@ -4484,8 +4473,11 @@ namespace Game
|
||||
|
||||
List<Difficulty> ParseSpawnDifficulties(string difficultyString, string table, ulong spawnId, uint mapId, List<Difficulty> mapDifficulties)
|
||||
{
|
||||
StringArray tokens = new StringArray(difficultyString, ',');
|
||||
List<Difficulty> difficulties = new List<Difficulty>();
|
||||
StringArray tokens = new StringArray(difficultyString, ',');
|
||||
if (tokens.Length == 0)
|
||||
return difficulties;
|
||||
|
||||
bool isTransportMap = IsTransportMap(mapId);
|
||||
foreach (string token in tokens)
|
||||
{
|
||||
@@ -4498,7 +4490,7 @@ namespace Game
|
||||
|
||||
if (!isTransportMap && !mapDifficulties.Contains(difficultyId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `{table}` has {table} (GUID: {spawnId}) has unsupported difficulty {difficultyId} for map (Id: {mapId}).");
|
||||
Log.outError(LogFilter.Sql, $"Table `{table}` has {table} (GUID: {spawnId}) has unsupported difficulty {difficultyId} for map (Id: {mapId}).");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5238,12 +5230,12 @@ namespace Game
|
||||
{
|
||||
for (uint i = 0; i < (int)Difficulty.Max; ++i)
|
||||
{
|
||||
if (Global.DB2Mgr.GetMapDifficultyData(dungeonEncounter.MapID, (Difficulty)i) != null)
|
||||
_dungeonEncounterStorage.Add(MathFunctions.MakePair64(dungeonEncounter.MapID, i), new DungeonEncounter(dungeonEncounter, creditType, creditEntry, lastEncounterDungeon));
|
||||
if (Global.DB2Mgr.GetMapDifficultyData((uint)dungeonEncounter.MapID, (Difficulty)i) != null)
|
||||
_dungeonEncounterStorage.Add(MathFunctions.MakePair64((uint)dungeonEncounter.MapID, i), new DungeonEncounter(dungeonEncounter, creditType, creditEntry, lastEncounterDungeon));
|
||||
}
|
||||
}
|
||||
else
|
||||
_dungeonEncounterStorage.Add(MathFunctions.MakePair64(dungeonEncounter.MapID, (uint)dungeonEncounter.DifficultyID), new DungeonEncounter(dungeonEncounter, creditType, creditEntry, lastEncounterDungeon));
|
||||
_dungeonEncounterStorage.Add(MathFunctions.MakePair64((uint)dungeonEncounter.MapID, (uint)dungeonEncounter.DifficultyID), new DungeonEncounter(dungeonEncounter, creditType, creditEntry, lastEncounterDungeon));
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
@@ -5450,7 +5442,7 @@ namespace Game
|
||||
uint count = 0;
|
||||
do
|
||||
{
|
||||
uint raceMask = result.Read<uint>(0);
|
||||
ulong raceMask = result.Read<ulong>(0);
|
||||
uint classMask = result.Read<uint>(1);
|
||||
uint spellId = result.Read<uint>(2);
|
||||
|
||||
@@ -5468,7 +5460,7 @@ namespace Game
|
||||
|
||||
for (int raceIndex = (int)Race.Human; raceIndex < (int)Race.Max; ++raceIndex)
|
||||
{
|
||||
if (raceMask == 0 || Convert.ToBoolean((1 << (raceIndex - 1)) & raceMask))
|
||||
if (raceMask == 0 || Convert.ToBoolean((1ul << (raceIndex - 1)) & raceMask))
|
||||
{
|
||||
for (int classIndex = (int)Class.Warrior; classIndex < (int)Class.Max; ++classIndex)
|
||||
{
|
||||
@@ -5508,11 +5500,11 @@ namespace Game
|
||||
|
||||
do
|
||||
{
|
||||
uint raceMask = result.Read<uint>(0);
|
||||
ulong raceMask = result.Read<ulong>(0);
|
||||
uint classMask = result.Read<uint>(1);
|
||||
uint spellId = result.Read<uint>(2);
|
||||
|
||||
if (raceMask != 0 && !raceMask.HasAnyFlag<uint>((uint)Race.RaceMaskAllPlayable))
|
||||
if (raceMask != 0 && !raceMask.HasAnyFlag((ulong)Race.RaceMaskAllPlayable))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Wrong race mask {0} in `playercreateinfo_cast_spell` table, ignoring.", raceMask);
|
||||
continue;
|
||||
@@ -5526,7 +5518,7 @@ namespace Game
|
||||
|
||||
for (int raceIndex = (int)Race.Human; raceIndex < (int)Race.Max; ++raceIndex)
|
||||
{
|
||||
if (raceMask == 0 || Convert.ToBoolean((1 << (raceIndex - 1)) & raceMask))
|
||||
if (raceMask == 0 || Convert.ToBoolean((1ul << (raceIndex - 1)) & raceMask))
|
||||
{
|
||||
for (int classIndex = (int)Class.Warrior; classIndex < (int)Class.Max; ++classIndex)
|
||||
{
|
||||
@@ -6266,35 +6258,35 @@ namespace Game
|
||||
_exclusiveQuestGroups.Clear();
|
||||
|
||||
SQLResult result = DB.World.Query("SELECT " +
|
||||
//0 1 2 3 4 5 6 7 8 9 10 11
|
||||
"ID, QuestType, QuestLevel, MaxScalingLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, " +
|
||||
//12 13 14 15 16 17 18 19 20 21 22
|
||||
//0 1 2 3 4 5 6 7 8 9 10 11 12
|
||||
"ID, QuestType, QuestLevel, ScalingFactionGroup, MaxScalingLevel, QuestPackageID, MinLevel, QuestSortID, QuestInfoID, SuggestedGroupNum, RewardNextQuest, RewardXPDifficulty, RewardXPMultiplier, " +
|
||||
//13 14 15 16 17 18 19 20 21 22 23
|
||||
"RewardMoney, RewardMoneyDifficulty, RewardMoneyMultiplier, RewardBonusMoney, RewardDisplaySpell1, RewardDisplaySpell2, RewardDisplaySpell3, RewardSpell, RewardHonor, RewardKillHonor, StartItem, " +
|
||||
//23 24 25 26 27
|
||||
"RewardArtifactXPDifficulty, RewardArtifactXPMultiplier, RewardArtifactCategoryID, Flags, FlagsEx, " +
|
||||
//28 29 30 31 32 33 34 35
|
||||
//24 25 26 27 28 29
|
||||
"RewardArtifactXPDifficulty, RewardArtifactXPMultiplier, RewardArtifactCategoryID, Flags, FlagsEx, FlagsEx2, " +
|
||||
//30 31 32 33 34 35 36 37
|
||||
"RewardItem1, RewardAmount1, ItemDrop1, ItemDropQuantity1, RewardItem2, RewardAmount2, ItemDrop2, ItemDropQuantity2, " +
|
||||
//36 37 38 39 40 41 42 43
|
||||
//38 39 40 41 42 43 44 45
|
||||
"RewardItem3, RewardAmount3, ItemDrop3, ItemDropQuantity3, RewardItem4, RewardAmount4, ItemDrop4, ItemDropQuantity4, " +
|
||||
//44 45 46 47 48 49
|
||||
//46 47 48 49 50 51
|
||||
"RewardChoiceItemID1, RewardChoiceItemQuantity1, RewardChoiceItemDisplayID1, RewardChoiceItemID2, RewardChoiceItemQuantity2, RewardChoiceItemDisplayID2, " +
|
||||
//50 51 52 53 54 55
|
||||
//52 53 54 55 56 57
|
||||
"RewardChoiceItemID3, RewardChoiceItemQuantity3, RewardChoiceItemDisplayID3, RewardChoiceItemID4, RewardChoiceItemQuantity4, RewardChoiceItemDisplayID4, " +
|
||||
//56 57 58 59 60 61
|
||||
//58 59 60 61 62 63
|
||||
"RewardChoiceItemID5, RewardChoiceItemQuantity5, RewardChoiceItemDisplayID5, RewardChoiceItemID6, RewardChoiceItemQuantity6, RewardChoiceItemDisplayID6, " +
|
||||
//62 63 64 65 66 67 68 69 70 71
|
||||
"POIContinent, POIx, POIy, POIPriority, RewardTitle, RewardArenaPoints, RewardSkillLineID, RewardNumSkillUps, PortraitGiver, PortraitTurnIn, " +
|
||||
//72 73 74 75 76 77 78 79
|
||||
//64 65 66 67 68 69 70 71 72 73 74
|
||||
"POIContinent, POIx, POIy, POIPriority, RewardTitle, RewardArenaPoints, RewardSkillLineID, RewardNumSkillUps, PortraitGiver, PortraitGiverMount, PortraitTurnIn, " +
|
||||
//75 76 77 78 79 80 81 82
|
||||
"RewardFactionID1, RewardFactionValue1, RewardFactionOverride1, RewardFactionCapIn1, RewardFactionID2, RewardFactionValue2, RewardFactionOverride2, RewardFactionCapIn2, " +
|
||||
//80 81 82 83 84 85 86 87
|
||||
//83 84 85 86 87 88 89 90
|
||||
"RewardFactionID3, RewardFactionValue3, RewardFactionOverride3, RewardFactionCapIn3, RewardFactionID4, RewardFactionValue4, RewardFactionOverride4, RewardFactionCapIn4, " +
|
||||
//88 89 90 91 92
|
||||
//91 92 93 94 95
|
||||
"RewardFactionID5, RewardFactionValue5, RewardFactionOverride5, RewardFactionCapIn5, RewardFactionFlags, " +
|
||||
//93 94 95 96 97 98 99 100
|
||||
//96 97 98 99 100 101 102 103
|
||||
"RewardCurrencyID1, RewardCurrencyQty1, RewardCurrencyID2, RewardCurrencyQty2, RewardCurrencyID3, RewardCurrencyQty3, RewardCurrencyID4, RewardCurrencyQty4, " +
|
||||
//101 102 103 104 105 106 107
|
||||
"AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, QuestRewardID, Expansion, " +
|
||||
//108 109 110 111 112 113 114 115 116
|
||||
//104 105 106 107 108 109 110
|
||||
"AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, TreasurePickerID, Expansion, " +
|
||||
//111 112 113 114 115 116 117 118 119
|
||||
"LogTitle, LogDescription, QuestDescription, AreaDescription, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, QuestCompletionLog" +
|
||||
" FROM quest_template");
|
||||
|
||||
@@ -7216,8 +7208,8 @@ namespace Game
|
||||
|
||||
uint count = 0;
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
||||
SQLResult result = DB.World.Query("SELECT QuestID, BlobIndex, Idx1, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, WorldMapAreaId, Floor, Priority, Flags, WorldEffectID, PlayerConditionID, WoDUnk1, AlwaysAllowMergingBlobs FROM quest_poi order by QuestID, Idx1");
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13
|
||||
SQLResult result = DB.World.Query("SELECT QuestID, BlobIndex, Idx1, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, UiMapID, Priority, Flags, WorldEffectID, PlayerConditionID, SpawnTrackingID, AlwaysAllowMergingBlobs FROM quest_poi order by QuestID, Idx1");
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
Log.outError(LogFilter.ServerLoading, "Loaded 0 quest POI definitions. DB table `quest_poi` is empty.");
|
||||
@@ -7247,33 +7239,32 @@ namespace Game
|
||||
|
||||
do
|
||||
{
|
||||
uint QuestID = Convert.ToUInt32(result.Read<int>(0));
|
||||
int BlobIndex = result.Read<int>(1);
|
||||
int Idx1 = result.Read<int>(2);
|
||||
int ObjectiveIndex = result.Read<int>(3);
|
||||
int QuestObjectiveID = result.Read<int>(4);
|
||||
int QuestObjectID = result.Read<int>(5);
|
||||
int MapID = result.Read<int>(6);
|
||||
int WorldMapAreaId = result.Read<int>(7);
|
||||
int Floor = result.Read<int>(8);
|
||||
int Priority = result.Read<int>(9);
|
||||
int Flags = result.Read<int>(10);
|
||||
int WorldEffectID = result.Read<int>(11);
|
||||
int PlayerConditionID = result.Read<int>(12);
|
||||
int WoDUnk1 = result.Read<int>(13);
|
||||
bool AlwaysAllowMergingBlobs = result.Read<bool>(14);
|
||||
uint questID = (uint)result.Read<int>(0);
|
||||
int blobIndex = result.Read<int>(1);
|
||||
int idx1 = result.Read<int>(2);
|
||||
int objectiveIndex = result.Read<int>(3);
|
||||
int questObjectiveID = result.Read<int>(4);
|
||||
int questObjectID = result.Read<int>(5);
|
||||
int mapID = result.Read<int>(6);
|
||||
int uiMapId = result.Read<int>(7);
|
||||
int priority = result.Read<int>(8);
|
||||
int flags = result.Read<int>(9);
|
||||
int worldEffectID = result.Read<int>(10);
|
||||
int playerConditionID = result.Read<int>(11);
|
||||
int spawnTrackingID = result.Read<int>(12);
|
||||
bool alwaysAllowMergingBlobs = result.Read<bool>(13);
|
||||
|
||||
if (Global.ObjectMgr.GetQuestTemplate(QuestID) == null)
|
||||
Log.outError(LogFilter.Sql, "`quest_poi` quest id ({0}) Idx1 ({1}) does not exist in `quest_template`", QuestID, Idx1);
|
||||
if (Global.ObjectMgr.GetQuestTemplate(questID) == null)
|
||||
Log.outError(LogFilter.Sql, "`quest_poi` quest id ({0}) Idx1 ({1}) does not exist in `quest_template`", questID, idx1);
|
||||
|
||||
QuestPOI POI = new QuestPOI(BlobIndex, ObjectiveIndex, QuestObjectiveID, QuestObjectID, MapID, WorldMapAreaId, Floor, Priority, Flags, WorldEffectID, PlayerConditionID, WoDUnk1, AlwaysAllowMergingBlobs);
|
||||
if (!POIs.ContainsKey(QuestID) || !POIs[QuestID].ContainsKey(Idx1))
|
||||
QuestPOI POI = new QuestPOI(blobIndex, objectiveIndex, questObjectiveID, questObjectID, mapID, uiMapId, priority, flags, worldEffectID, playerConditionID, spawnTrackingID, alwaysAllowMergingBlobs);
|
||||
if (!POIs.ContainsKey(questID) || !POIs[questID].ContainsKey(idx1))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table quest_poi references unknown quest points for quest {0} POI id {1}", QuestID, BlobIndex);
|
||||
Log.outError(LogFilter.Sql, "Table quest_poi references unknown quest points for quest {0} POI id {1}", questID, blobIndex);
|
||||
continue;
|
||||
}
|
||||
POI.points = POIs[QuestID][Idx1];
|
||||
_questPOIStorage.Add(QuestID, POI);
|
||||
POI.points = POIs[questID][idx1];
|
||||
_questPOIStorage.Add(questID, POI);
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
@@ -7502,8 +7493,8 @@ namespace Game
|
||||
{
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
|
||||
// 0 1
|
||||
SQLResult result = DB.World.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`");
|
||||
// 0 1
|
||||
SQLResult result = DB.World.Query("SELECT TerrainSwapMap, UiMapPhaseId FROM `terrain_worldmap`");
|
||||
|
||||
if (result.IsEmpty())
|
||||
{
|
||||
@@ -7515,7 +7506,7 @@ namespace Game
|
||||
do
|
||||
{
|
||||
uint mapId = result.Read<uint>(0);
|
||||
uint worldMapArea = result.Read<uint>(1);
|
||||
uint uiMapPhaseId = result.Read<uint>(1);
|
||||
|
||||
if (!CliDB.MapStorage.ContainsKey(mapId))
|
||||
{
|
||||
@@ -7523,9 +7514,9 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CliDB.WorldMapAreaStorage.ContainsKey(worldMapArea))
|
||||
if (!Global.DB2Mgr.IsUiMapPhase((int)uiMapPhaseId))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "WorldMapArea {0} defined in `terrain_worldmap` does not exist, skipped.", worldMapArea);
|
||||
Log.outError(LogFilter.Sql, $"Phase {uiMapPhaseId} defined in `terrain_worldmap` is not a valid terrain swap phase, skipped.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -7534,7 +7525,7 @@ namespace Game
|
||||
|
||||
TerrainSwapInfo terrainSwapInfo = _terrainSwapInfoById[mapId];
|
||||
terrainSwapInfo.Id = mapId;
|
||||
terrainSwapInfo.UiWorldMapAreaIDSwaps.Add(worldMapArea);
|
||||
terrainSwapInfo.UiMapPhaseIDs.Add(uiMapPhaseId);
|
||||
|
||||
++count;
|
||||
} while (result.NextRow());
|
||||
@@ -7783,10 +7774,6 @@ namespace Game
|
||||
{
|
||||
return _terrainSwapInfoById.LookupByKey(terrainSwapId);
|
||||
}
|
||||
public List<TerrainSwapInfo> GetTerrainSwapsForMap(uint mapId)
|
||||
{
|
||||
return _terrainSwapInfoByMap.LookupByKey(mapId);
|
||||
}
|
||||
public List<SpellClickInfo> GetSpellClickInfoMapBounds(uint creature_id)
|
||||
{
|
||||
return _spellClickInfoStorage.LookupByKey(creature_id);
|
||||
@@ -7799,6 +7786,7 @@ namespace Game
|
||||
{
|
||||
return _skillTiers.LookupByKey(skillTierId);
|
||||
}
|
||||
public MultiMap<uint, TerrainSwapInfo> GetTerrainSwaps() { return _terrainSwapInfoByMap; }
|
||||
|
||||
//Locales
|
||||
public void LoadCreatureLocales()
|
||||
@@ -8457,7 +8445,7 @@ namespace Game
|
||||
do
|
||||
{
|
||||
byte level = result.Read<byte>(0);
|
||||
uint raceMask = result.Read<uint>(1);
|
||||
ulong raceMask = result.Read<ulong>(1);
|
||||
uint mailTemplateId = result.Read<uint>(2);
|
||||
uint senderEntry = result.Read<uint>(3);
|
||||
|
||||
@@ -8832,7 +8820,7 @@ namespace Game
|
||||
uint oldMSTime = Time.GetMSTime();
|
||||
_playerChoices.Clear();
|
||||
|
||||
SQLResult choiceResult = DB.World.Query("SELECT ChoiceId, UiTextureKitId, Question, HideWarboardHeader FROM playerchoice");
|
||||
SQLResult choiceResult = DB.World.Query("SELECT ChoiceId, UiTextureKitId, Question, HideWarboardHeader, KeepOpenAfterChoice FROM playerchoice");
|
||||
if (choiceResult.IsEmpty())
|
||||
{
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 player choices. DB table `playerchoice` is empty.");
|
||||
@@ -8852,12 +8840,13 @@ namespace Game
|
||||
choice.UiTextureKitId = choiceResult.Read<int>(1);
|
||||
choice.Question = choiceResult.Read<string>(2);
|
||||
choice.HideWarboardHeader = choiceResult.Read<bool>(3);
|
||||
choice.KeepOpenAfterChoice = choiceResult.Read<bool>(4);
|
||||
|
||||
_playerChoices[choice.ChoiceId] = choice;
|
||||
|
||||
} while (choiceResult.NextRow());
|
||||
|
||||
SQLResult responses = DB.World.Query("SELECT ChoiceId, ResponseId, ChoiceArtFileId, Header, Answer, Description, Confirmation FROM playerchoice_response ORDER BY `Index` ASC");
|
||||
SQLResult responses = DB.World.Query("SELECT ChoiceId, ResponseId, ChoiceArtFileId, Flags, WidgetSetID, GroupID, Header, Answer, Description, Confirmation FROM playerchoice_response ORDER BY `Index` ASC");
|
||||
if (!responses.IsEmpty())
|
||||
{
|
||||
do
|
||||
@@ -8876,10 +8865,13 @@ namespace Game
|
||||
|
||||
response.ResponseId = responseId;
|
||||
response.ChoiceArtFileId = responses.Read<int>(2);
|
||||
response.Header = responses.Read<string>(3);
|
||||
response.Answer = responses.Read<string>(4);
|
||||
response.Description = responses.Read<string>(5);
|
||||
response.Confirmation = responses.Read<string>(6);
|
||||
response.Flags = responses.Read<int>(3);
|
||||
response.WidgetSetID = responses.Read<uint>(4);
|
||||
response.GroupID = responses.Read<byte>(5);
|
||||
response.Header = responses.Read<string>(6);
|
||||
response.Answer = responses.Read<string>(7);
|
||||
response.Description = responses.Read<string>(8);
|
||||
response.Confirmation = responses.Read<string>(9);
|
||||
++responseCount;
|
||||
|
||||
choice.Responses[responseId] = response;
|
||||
@@ -9156,7 +9148,7 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
public MailLevelReward GetMailLevelReward(uint level, uint raceMask)
|
||||
public MailLevelReward GetMailLevelReward(uint level, ulong raceMask)
|
||||
{
|
||||
var mailList = _mailLevelRewardStorage.LookupByKey((byte)level);
|
||||
if (mailList.Empty())
|
||||
@@ -9328,6 +9320,8 @@ namespace Game
|
||||
return 100;
|
||||
case Expansion.Legion:
|
||||
return 110;
|
||||
case Expansion.BattleForAzeroth:
|
||||
return 120;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -9377,7 +9371,7 @@ namespace Game
|
||||
if (node.ContinentID != mapid || !node.Flags.HasAnyFlag(requireFlag))
|
||||
continue;
|
||||
|
||||
byte field = (byte)((i - 1) / 8);
|
||||
uint field = (i - 1) / 8;
|
||||
byte submask = (byte)(1 << (int)((i - 1) % 8));
|
||||
|
||||
// skip not taxi network nodes
|
||||
@@ -9426,7 +9420,8 @@ namespace Game
|
||||
}
|
||||
public uint GetTaxiMountDisplayId(uint id, Team team, bool allowed_alt_team = false)
|
||||
{
|
||||
uint mount_id = 0;
|
||||
CreatureModel mountModel = new CreatureModel();
|
||||
CreatureTemplate mount_info = null;
|
||||
|
||||
// select mount creature id
|
||||
TaxiNodesRecord node = CliDB.TaxiNodesStorage.LookupByKey(id);
|
||||
@@ -9446,22 +9441,23 @@ namespace Game
|
||||
mount_entry = team == Team.Alliance ? node.MountCreatureID[0] : node.MountCreatureID[1];
|
||||
}
|
||||
|
||||
CreatureTemplate mount_info = GetCreatureTemplate(mount_entry);
|
||||
mount_info = GetCreatureTemplate(mount_entry);
|
||||
if (mount_info != null)
|
||||
{
|
||||
mount_id = mount_info.GetRandomValidModelId();
|
||||
if (mount_id == 0)
|
||||
CreatureModel model = mount_info.GetRandomValidModel();
|
||||
if (model == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "No displayid found for the taxi mount with the entry {0}! Can't load it!", mount_entry);
|
||||
Log.outError(LogFilter.Sql, $"No displayid found for the taxi mount with the entry {mount_entry}! Can't load it!");
|
||||
return 0;
|
||||
}
|
||||
mountModel = model;
|
||||
}
|
||||
}
|
||||
|
||||
// minfo is not actually used but the mount_id was updated
|
||||
GetCreatureModelRandomGender(ref mount_id);
|
||||
GetCreatureModelRandomGender(ref mountModel, mount_info);
|
||||
|
||||
return mount_id;
|
||||
return mountModel.CreatureDisplayID;
|
||||
}
|
||||
|
||||
public AreaTriggerStruct GetAreaTrigger(uint trigger)
|
||||
@@ -10156,22 +10152,21 @@ namespace Game
|
||||
|
||||
public class QuestPOI
|
||||
{
|
||||
public QuestPOI(int _BlobIndex, int _ObjectiveIndex, int _QuestObjectiveID, int _QuestObjectID, int _MapID, int _WorldMapAreaID, int _Foor, int _Priority, int _Flags,
|
||||
int _WorldEffectID, int _PlayerConditionID, int _UnkWoD1, bool _AlwaysAllowMergingBlobs)
|
||||
public QuestPOI(int blobIndex, int objectiveIndex, int questObjectiveID, int questObjectID, int mapID, int uiMapID, int priority, int flags,
|
||||
int worldEffectID, int playerConditionID, int spawnTrackingID, bool alwaysAllowMergingBlobs)
|
||||
{
|
||||
BlobIndex = _BlobIndex;
|
||||
ObjectiveIndex = _ObjectiveIndex;
|
||||
QuestObjectiveID = _QuestObjectiveID;
|
||||
QuestObjectID = _QuestObjectID;
|
||||
MapID = _MapID;
|
||||
WorldMapAreaID = _WorldMapAreaID;
|
||||
Floor = _Foor;
|
||||
Priority = _Priority;
|
||||
Flags = _Flags;
|
||||
WorldEffectID = _WorldEffectID;
|
||||
PlayerConditionID = _PlayerConditionID;
|
||||
UnkWoD1 = _UnkWoD1;
|
||||
AlwaysAllowMergingBlobs = _AlwaysAllowMergingBlobs;
|
||||
BlobIndex = blobIndex;
|
||||
ObjectiveIndex = objectiveIndex;
|
||||
QuestObjectiveID = questObjectiveID;
|
||||
QuestObjectID = questObjectID;
|
||||
MapID = mapID;
|
||||
UiMapID = uiMapID;
|
||||
Priority = priority;
|
||||
Flags = flags;
|
||||
WorldEffectID = worldEffectID;
|
||||
PlayerConditionID = playerConditionID;
|
||||
SpawnTrackingID = spawnTrackingID;
|
||||
AlwaysAllowMergingBlobs = alwaysAllowMergingBlobs;
|
||||
}
|
||||
|
||||
public int BlobIndex;
|
||||
@@ -10179,13 +10174,12 @@ namespace Game
|
||||
public int QuestObjectiveID;
|
||||
public int QuestObjectID;
|
||||
public int MapID;
|
||||
public int WorldMapAreaID;
|
||||
public int Floor;
|
||||
public int UiMapID;
|
||||
public int Priority;
|
||||
public int Flags;
|
||||
public int WorldEffectID;
|
||||
public int PlayerConditionID;
|
||||
public int UnkWoD1;
|
||||
public int SpawnTrackingID;
|
||||
public List<QuestPOIPoint> points = new List<QuestPOIPoint>();
|
||||
public bool AlwaysAllowMergingBlobs;
|
||||
}
|
||||
@@ -10230,14 +10224,14 @@ namespace Game
|
||||
|
||||
public class MailLevelReward
|
||||
{
|
||||
public MailLevelReward(uint _raceMask = 0, uint _mailTemplateId = 0, uint _senderEntry = 0)
|
||||
public MailLevelReward(ulong _raceMask = 0, uint _mailTemplateId = 0, uint _senderEntry = 0)
|
||||
{
|
||||
raceMask = _raceMask;
|
||||
mailTemplateId = _mailTemplateId;
|
||||
senderEntry = _senderEntry;
|
||||
}
|
||||
|
||||
public uint raceMask;
|
||||
public ulong raceMask;
|
||||
public uint mailTemplateId;
|
||||
public uint senderEntry;
|
||||
}
|
||||
@@ -10500,7 +10494,7 @@ namespace Game
|
||||
}
|
||||
|
||||
public uint Id;
|
||||
public List<uint> UiWorldMapAreaIDSwaps = new List<uint>();
|
||||
public List<uint> UiMapPhaseIDs = new List<uint>();
|
||||
}
|
||||
|
||||
public class PhaseInfoStruct
|
||||
@@ -10622,6 +10616,9 @@ namespace Game
|
||||
{
|
||||
public int ResponseId;
|
||||
public int ChoiceArtFileId;
|
||||
public int Flags;
|
||||
public uint WidgetSetID;
|
||||
public byte GroupID;
|
||||
public string Header;
|
||||
public string Answer;
|
||||
public string Description;
|
||||
@@ -10641,6 +10638,7 @@ namespace Game
|
||||
public string Question;
|
||||
public List<PlayerChoiceResponse> Responses = new List<PlayerChoiceResponse>();
|
||||
public bool HideWarboardHeader;
|
||||
public bool KeepOpenAfterChoice;
|
||||
}
|
||||
|
||||
public class RaceUnlockRequirement
|
||||
|
||||
@@ -644,7 +644,7 @@ namespace Game.Groups
|
||||
// Remove the groups permanent instance bindings
|
||||
foreach (var difficultyDic in m_boundInstances.Values)
|
||||
{
|
||||
foreach (var pair in difficultyDic)
|
||||
foreach (var pair in difficultyDic.ToList())
|
||||
{
|
||||
// Do not unbind saves of instances that already had map created (a newLeader entered)
|
||||
// forcing a new instance with another leader requires group disbanding (confirmed on retail)
|
||||
@@ -1175,6 +1175,7 @@ namespace Game.Groups
|
||||
else
|
||||
{
|
||||
item.is_blocked = false;
|
||||
item.rollWinnerGUID = player.GetGUID();
|
||||
player.SendEquipError(msg, null, null, roll.itemid);
|
||||
}
|
||||
}
|
||||
@@ -1225,6 +1226,7 @@ namespace Game.Groups
|
||||
else
|
||||
{
|
||||
item.is_blocked = false;
|
||||
item.rollWinnerGUID = player.GetGUID();
|
||||
player.SendEquipError(msg, null, null, roll.itemid);
|
||||
}
|
||||
}
|
||||
@@ -1984,6 +1986,9 @@ namespace Game.Groups
|
||||
if (save == null || isBGGroup() || isBFGroup())
|
||||
return null;
|
||||
|
||||
if (!m_boundInstances.ContainsKey(save.GetDifficultyID()))
|
||||
m_boundInstances[save.GetDifficultyID()] = new Dictionary<uint, InstanceBind>();
|
||||
|
||||
if (!m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
|
||||
m_boundInstances[save.GetDifficultyID()][save.GetMapId()] = new InstanceBind();
|
||||
|
||||
|
||||
@@ -2786,7 +2786,7 @@ namespace Game.Guilds
|
||||
ObjectGuid playerGUID = ObjectGuid.Create(HighGuid.Player, m_playerGuid1);
|
||||
ObjectGuid otherGUID = ObjectGuid.Create(HighGuid.Player, m_playerGuid2);
|
||||
|
||||
GuildEventEntry eventEntry;
|
||||
GuildEventEntry eventEntry = new GuildEventEntry();
|
||||
eventEntry.PlayerGUID = playerGUID;
|
||||
eventEntry.OtherGUID = otherGUID;
|
||||
eventEntry.TransactionType = (byte)m_eventType;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user