BFA Update (still lots of testing to do tho)

This commit is contained in:
hondacrx
2018-12-10 12:46:25 -05:00
parent 468b053946
commit 8e20114e10
256 changed files with 35613 additions and 10459 deletions
+1
View File
@@ -261,6 +261,7 @@ namespace Game.AI
me.ResetPlayerDamageReq();
me.SetLastDamagedTime(0);
me.SetCannotReachTarget(false);
me.DoNotReacquireTarget();
if (me.IsInEvadeMode())
return false;
+6
View File
@@ -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
{
+11 -5
View File
@@ -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:
+34 -36
View File
@@ -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());
+11 -7
View File
@@ -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);
+3 -2
View File
@@ -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;
+3 -3
View File
@@ -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);
}
}
+76 -1
View File
@@ -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))
{
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+10 -2
View File
@@ -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);
+5 -5
View File
@@ -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;
+5 -1
View File
@@ -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;
+4 -4
View File
@@ -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;
+4 -4
View File
@@ -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);
+1 -1
View File
@@ -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)))
+5 -3
View File
@@ -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);
}
+13 -13
View File
@@ -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;
+3 -1
View File
@@ -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;
+10 -1
View File
@@ -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;
}
}
+17
View File
@@ -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()
+10 -10
View File
@@ -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];
+43 -26
View File
@@ -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;
}
+202 -236
View File
@@ -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
+1 -1
View File
@@ -156,7 +156,7 @@ namespace Game.DataStorage
}
}
FlyByCameraStorage[dbcentry.ID] = cameras;
FlyByCameraStorage[dbcentry.Id] = cameras;
}
public static void LoadM2Cameras(string dataPath)
+84 -75
View File
@@ -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;
}
+37 -36
View File
@@ -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];
}
}
+140 -109
View File
@@ -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;
}
+30 -30
View File
@@ -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
+38 -8
View File
@@ -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 -19
View File
@@ -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; }
}
}
}
+62 -61
View File
@@ -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
+13 -13
View File
@@ -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];
}
}
+113 -115
View File
@@ -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
+30 -28
View File
@@ -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];
+50 -48
View File
@@ -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;
}
}
+52 -51
View File
@@ -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;
}
}
+2 -2
View File
@@ -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
+8 -7
View File
@@ -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;
}
+138 -140
View File
@@ -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;
}
}
+25 -23
View File
@@ -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;
}
}
+59 -8
View File
@@ -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];
}
}
+37 -37
View File
@@ -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)
+27 -66
View File
@@ -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;
}
}
+1 -1
View File
@@ -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;
+14 -3
View File
@@ -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;
}
+1 -1
View File
@@ -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;
+45 -27
View File
@@ -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))
+65 -58
View File
@@ -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;
+8 -2
View File
@@ -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;
+28 -7
View File
@@ -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))
+1 -1
View File
@@ -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
}
+16 -83
View File
@@ -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];
+1 -6
View File
@@ -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);
+153 -78
View File
@@ -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;
}
}
}
+2 -2
View File
@@ -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);
}
}
+3 -3
View File
@@ -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;
}
+83 -84
View File
@@ -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);
+3 -2
View File
@@ -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)
+26 -35
View File
@@ -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)
+5 -2
View File
@@ -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();
+67 -109
View File
@@ -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; }
+40 -19
View File
@@ -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)
+161 -79
View File
@@ -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;
+14 -53
View File
@@ -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;
}
}
}
+100 -102
View File
@@ -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;
+2 -2
View File
@@ -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)
{
+12 -12
View File
@@ -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;
}
+70 -74
View File
@@ -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()
-515
View File
@@ -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;
}
}
}
+39 -28
View File
@@ -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];
}
}
}
+26 -15
View File
@@ -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; }
+3 -1
View File
@@ -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()
+24 -6
View File
@@ -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;
+13 -2
View File
@@ -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;
+16 -3
View File
@@ -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);
}
+1 -1
View File
@@ -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
+21 -33
View File
@@ -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);
+15 -12
View File
@@ -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);
+15
View File
@@ -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;
}
}
+10 -10
View File
@@ -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;
+296 -298
View File
@@ -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
+6 -1
View File
@@ -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();
+1 -1
View File
@@ -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