Ported .Net Core commits:

hondacrx:
- Initial commit: Switch to .Net Core 2.0
- Fix build and removed not needed files
Fabi:
- Updated solution platforms.
- Changed folder structure.
- Change library target framework to netstandard2.0.
- Updated solution platforms again...
- Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
Fabian
2017-10-26 17:23:44 +02:00
parent 227702e19c
commit a3dc7b3f48
844 changed files with 26064 additions and 1824 deletions
+601
View File
@@ -0,0 +1,601 @@
/*
* Copyright (C) 2012-2017 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 Framework.Collections;
using Framework.Constants;
using Framework.Database;
using Game.DataStorage;
using Game.Entities;
using Game.Network.Packets;
using System;
using System.Collections.Generic;
namespace Game
{
public class Quest
{
public Quest(SQLFields fields)
{
Id = fields.Read<uint>(0);
Type = (QuestType)fields.Read<byte>(1);
Level = fields.Read<int>(2);
PackageID = fields.Read<uint>(3);
MinLevel = fields.Read<int>(4);
QuestSortID = fields.Read<short>(5);
QuestInfoID = fields.Read<ushort>(6);
SuggestedPlayers = fields.Read<uint>(7);
NextQuestInChain = fields.Read<uint>(8);
RewardXPDifficulty = fields.Read<uint>(9);
RewardXPMultiplier = fields.Read<float>(10);
RewardMoney = fields.Read<int>(11);
RewardMoneyDifficulty = fields.Read<uint>(12);
RewardMoneyMultiplier = fields.Read<float>(13);
RewardBonusMoney = fields.Read<uint>(14);
for (int i = 0; i < SharedConst.QuestRewardDisplaySpellCount; ++i)
RewardDisplaySpell[i] = fields.Read<uint>(15 + i);
RewardSpell = fields.Read<uint>(18);
RewardHonor = fields.Read<uint>(19);
RewardKillHonor = fields.Read<uint>(20);
SourceItemId = fields.Read<uint>(21);
RewardArtifactXPDifficulty = fields.Read<uint>(22);
RewardArtifactXPMultiplier = fields.Read<float>(23);
RewardArtifactCategoryID = fields.Read<uint>(24);
Flags = (QuestFlags)fields.Read<uint>(25);
FlagsEx = (QuestFlagsEx)fields.Read<uint>(26);
for (int i = 0; i < SharedConst.QuestItemDropCount; ++i)
{
RewardItemId[i] = fields.Read<uint>(27 + i * 4);
RewardItemCount[i] = fields.Read<uint>(28 + i * 4);
ItemDrop[i] = fields.Read<uint>(29 + i * 4);
ItemDropQuantity[i] = fields.Read<uint>(30 + i * 4);
if (RewardItemId[i] != 0)
++_rewItemsCount;
}
for (int i = 0; i < SharedConst.QuestRewardChoicesCount; ++i)
{
RewardChoiceItemId[i] = fields.Read<uint>(43 + i * 3);
RewardChoiceItemCount[i] = fields.Read<uint>(44 + i * 3);
RewardChoiceItemDisplayId[i] = fields.Read<uint>(45 + i * 3);
if (RewardChoiceItemId[i] != 0)
++_rewChoiceItemsCount;
}
POIContinent = fields.Read<uint>(61);
POIx = fields.Read<float>(62);
POIy = fields.Read<float>(63);
POIPriority = fields.Read<uint>(64);
RewardTitleId = fields.Read<uint>(65);
RewardArenaPoints = fields.Read<int>(66);
RewardSkillId = fields.Read<uint>(67);
RewardSkillPoints = fields.Read<uint>(68);
QuestGiverPortrait = fields.Read<uint>(69);
QuestTurnInPortrait = fields.Read<uint>(70);
for (int i = 0; i < SharedConst.QuestRewardReputationsCount; ++i)
{
RewardFactionId[i] = fields.Read<uint>(71 + i * 4);
RewardFactionValue[i] = fields.Read<int>(72 + i * 4);
RewardFactionOverride[i] = fields.Read<int>(73 + i * 4);
RewardFactionCapIn[i] = fields.Read<uint>(74 + i * 4);
}
RewardReputationMask = fields.Read<uint>(91);
for (int i = 0; i < SharedConst.QuestRewardCurrencyCount; ++i)
{
RewardCurrencyId[i] = fields.Read<uint>(92 + i * 2);
RewardCurrencyCount[i] = fields.Read<uint>(93 + i * 2);
if (RewardCurrencyId[i] != 0)
++_rewCurrencyCount;
}
SoundAccept = fields.Read<uint>(100);
SoundTurnIn = fields.Read<uint>(101);
AreaGroupID = fields.Read<uint>(102);
LimitTime = fields.Read<uint>(103);
AllowableRaces = fields.Read<int>(104);
QuestRewardID = fields.Read<uint>(105);
Expansion = fields.Read<int>(106);
LogTitle = fields.Read<string>(107);
LogDescription = fields.Read<string>(108);
QuestDescription = fields.Read<string>(109);
AreaDescription = fields.Read<string>(110);
PortraitGiverText = fields.Read<string>(111);
PortraitGiverName = fields.Read<string>(112);
PortraitTurnInText = fields.Read<string>(113);
PortraitTurnInName = fields.Read<string>(114);
QuestCompletionLog = fields.Read<string>(115);
}
public void LoadQuestDetails(SQLFields fields)
{
for (int i = 0; i < SharedConst.QuestEmoteCount; ++i)
{
ushort emoteId = fields.Read<ushort>(1 + i);
if (!CliDB.EmotesStorage.ContainsKey(emoteId))
{
Log.outError(LogFilter.Sql, "Table `quest_details` has non-existing Emote{0} ({1}) set for quest {2}. Skipped.", 1 + i, emoteId, fields.Read<uint>(0));
continue;
}
DetailsEmote[i] = emoteId;
}
for (int i = 0; i < SharedConst.QuestEmoteCount; ++i)
DetailsEmoteDelay[i] = fields.Read<uint>(5 + i);
}
public void LoadQuestRequestItems(SQLFields fields)
{
EmoteOnComplete = fields.Read<ushort>(1);
EmoteOnIncomplete = fields.Read<ushort>(2);
if (!CliDB.EmotesStorage.ContainsKey(EmoteOnComplete))
Log.outError(LogFilter.Sql, "Table `quest_request_items` has non-existing EmoteOnComplete ({0}) set for quest {1}.", EmoteOnComplete, fields.Read<uint>(0));
if (!CliDB.EmotesStorage.ContainsKey(EmoteOnIncomplete))
Log.outError(LogFilter.Sql, "Table `quest_request_items` has non-existing EmoteOnIncomplete ({0}) set for quest {1}.", EmoteOnIncomplete, fields.Read<uint>(0));
EmoteOnCompleteDelay = fields.Read<uint>(3);
EmoteOnIncompleteDelay = fields.Read<uint>(4);
RequestItemsText = fields.Read<string>(5);
}
public void LoadQuestOfferReward(SQLFields fields)
{
for (int i = 0; i < SharedConst.QuestEmoteCount; ++i)
{
ushort emoteId = fields.Read<ushort>(1 + i);
if (!CliDB.EmotesStorage.ContainsKey(emoteId))
{
Log.outError(LogFilter.Sql, "Table `quest_offer_reward` has non-existing Emote{0} ({1}) set for quest {2}. Skipped.", 1 + i, emoteId, fields.Read<uint>(0));
continue;
}
OfferRewardEmote[i] = emoteId;
}
for (int i = 0; i < SharedConst.QuestEmoteCount; ++i)
OfferRewardEmoteDelay[i] = fields.Read<uint>(5 + i);
OfferRewardText = fields.Read<string>(9);
}
public void LoadQuestTemplateAddon(SQLFields fields)
{
MaxLevel = fields.Read<byte>(1);
AllowableClasses = fields.Read<uint>(2);
SourceSpellID = fields.Read<uint>(3);
PrevQuestId = fields.Read<int>(4);
NextQuestId = fields.Read<int>(5);
ExclusiveGroup = fields.Read<int>(6);
RewardMailTemplateId = fields.Read<uint>(7);
RewardMailDelay = fields.Read<uint>(8);
RequiredSkillId = fields.Read<ushort>(9);
RequiredSkillPoints = fields.Read<ushort>(10);
RequiredMinRepFaction = fields.Read<ushort>(11);
RequiredMaxRepFaction = fields.Read<ushort>(12);
RequiredMinRepValue = fields.Read<int>(13);
RequiredMaxRepValue = fields.Read<int>(14);
SourceItemIdCount = fields.Read<byte>(15);
RewardMailSenderEntry = fields.Read<uint>(16);
SpecialFlags = (QuestSpecialFlags)fields.Read<byte>(17);
if (SpecialFlags.HasAnyFlag(QuestSpecialFlags.AutoAccept))
Flags |= QuestFlags.AutoAccept;
}
public void LoadQuestObjective(SQLFields fields)
{
QuestObjective obj = new QuestObjective();
obj.ID = fields.Read<uint>(0);
obj.QuestID = fields.Read<uint>(1);
obj.Type = (QuestObjectiveType)fields.Read<byte>(2);
obj.StorageIndex = fields.Read<sbyte>(3);
obj.ObjectID = fields.Read<int>(4);
obj.Amount = fields.Read<int>(5);
obj.Flags = (QuestObjectiveFlags)fields.Read<uint>(6);
obj.Flags2 = fields.Read<uint>(7);
obj.ProgressBarWeight = fields.Read<float>(8);
obj.Description = fields.Read<string>(9);
Objectives.Add(obj);
}
public void LoadQuestObjectiveVisualEffect(SQLFields fields)
{
uint objID = fields.Read<uint>(1);
foreach (QuestObjective obj in Objectives)
{
if (obj.ID == objID)
{
byte effectIndex = fields.Read<byte>(3);
if (obj.VisualEffects == null)
obj.VisualEffects = new int[effectIndex + 1];
if (effectIndex >= obj.VisualEffects.Length)
Array.Resize(ref obj.VisualEffects, effectIndex + 1);
obj.VisualEffects[effectIndex] = fields.Read<int>(4);
break;
}
}
}
public uint XPValue(uint playerLevel)
{
if (playerLevel != 0)
{
uint questLevel = (Level == -1 ? playerLevel : (uint)Level);
QuestXPRecord questXp = CliDB.QuestXPStorage.LookupByKey(questLevel);
if (questXp == null || RewardXPDifficulty >= 10)
return 0;
float multiplier = 1.0f;
if (questLevel != playerLevel)
multiplier = CliDB.XpGameTable.GetRow(Math.Min(playerLevel, questLevel)).Divisor / CliDB.XpGameTable.GetRow(playerLevel).Divisor;
int diffFactor = (int)(2 * (questLevel - playerLevel) + 20);
if (diffFactor < 1)
diffFactor = 1;
else if (diffFactor > 10)
diffFactor = 10;
uint xp = (uint)(diffFactor * questXp.Exp[RewardXPDifficulty] * RewardXPMultiplier / 10 * multiplier);
if (xp <= 100)
xp = 5 * ((xp + 2) / 5);
else if (xp <= 500)
xp = 10 * ((xp + 5) / 10);
else if (xp <= 1000)
xp = 25 * ((xp + 12) / 25);
else
xp = 50 * ((xp + 25) / 50);
return xp;
}
return 0;
}
public uint MoneyValue(uint playerLevel)
{
uint level = Level == -1 ? playerLevel : (uint)Level;
QuestMoneyRewardRecord money = CliDB.QuestMoneyRewardStorage.LookupByKey(level);
if (money != null)
return (uint)(money.Money[RewardMoneyDifficulty] * RewardMoneyMultiplier);
else
return 0;
}
public void BuildQuestRewards(QuestRewards rewards, Player player)
{
rewards.ChoiceItemCount = GetRewChoiceItemsCount();
rewards.ItemCount = GetRewItemsCount();
rewards.Money = player.GetQuestMoneyReward(this);
rewards.XP = player.GetQuestXPReward(this);
rewards.ArtifactCategoryID = RewardArtifactCategoryID;
rewards.Title = RewardTitleId;
rewards.FactionFlags = RewardReputationMask;
for (int i = 0; i < SharedConst.QuestRewardDisplaySpellCount; ++i)
rewards.SpellCompletionDisplayID[i] = (int)RewardDisplaySpell[i];
rewards.SpellCompletionID = RewardSpell;
rewards.SkillLineID = RewardSkillId;
rewards.NumSkillUps = RewardSkillPoints;
rewards.RewardID = QuestRewardID;
for (int i = 0; i < SharedConst.QuestRewardChoicesCount; ++i)
{
rewards.ChoiceItems[i].ItemID = RewardChoiceItemId[i];
rewards.ChoiceItems[i].Quantity = RewardChoiceItemCount[i];
}
for (int i = 0; i < SharedConst.QuestRewardItemCount; ++i)
{
rewards.ItemID[i] = RewardItemId[i];
rewards.ItemQty[i] = RewardItemCount[i];
}
for (int i = 0; i < SharedConst.QuestRewardReputationsCount; ++i)
{
rewards.FactionID[i] = RewardFactionId[i];
rewards.FactionOverride[i] = RewardFactionOverride[i];
rewards.FactionValue[i] = RewardFactionValue[i];
rewards.FactionCapIn[i] = (int)RewardFactionCapIn[i];
}
for (int i = 0; i < SharedConst.QuestRewardCurrencyCount; ++i)
{
rewards.CurrencyID[i] = RewardCurrencyId[i];
rewards.CurrencyQty[i] = RewardCurrencyCount[i];
}
}
public uint GetRewMoneyMaxLevel()
{
// If Quest has flag to not give money on max level, it's 0
if (HasFlag(QuestFlags.NoMoneyFromXp))
return 0;
// Else, return the rewarded copper sum modified by the rate
return (uint)(RewardBonusMoney * WorldConfig.GetFloatValue(WorldCfg.RateMoneyMaxLevelQuest));
}
public bool IsAutoAccept()
{
return !WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) && HasFlag(QuestFlags.AutoAccept);
}
public bool IsAutoComplete()
{
return !WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoComplete) && Type == QuestType.AutoComplete;
}
public bool IsRaidQuest(Difficulty difficulty)
{
switch ((QuestInfos)QuestInfoID)
{
case QuestInfos.Raid:
return true;
case QuestInfos.Raid10:
return difficulty == Difficulty.Raid10N || difficulty == Difficulty.Raid10HC;
case QuestInfos.Raid25:
return difficulty == Difficulty.Raid25N || difficulty == Difficulty.Raid25HC;
default:
break;
}
if (Flags.HasAnyFlag(QuestFlags.Raid))
return true;
return false;
}
public bool IsAllowedInRaid(Difficulty difficulty)
{
if (IsRaidQuest(difficulty))
return true;
return WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreRaid);
}
public uint CalculateHonorGain(uint level)
{
uint honor = 0;
return honor;
}
public bool CanIncreaseRewardedQuestCounters()
{
// Dungeon Finder/Daily/Repeatable (if not weekly, monthly or seasonal) quests are never considered rewarded serverside.
// This affects counters and client requests for completed quests.
return (!IsDFQuest() && !IsDaily() && (!IsRepeatable() || IsWeekly() || IsMonthly() || IsSeasonal()));
}
public bool HasFlag(QuestFlags flag) { return (Flags & flag) != 0; }
public void SetFlag(QuestFlags flag) { Flags |= flag; }
public bool HasSpecialFlag(QuestSpecialFlags flag) { return (SpecialFlags & flag) != 0; }
public void SetSpecialFlag(QuestSpecialFlags flag) { SpecialFlags |= flag; }
public bool HasFlagEx(QuestFlagsEx flag) { return (FlagsEx & flag) != 0; }
// table data accessors:
public bool IsRepeatable() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.Repeatable); }
public bool IsDaily() { return Flags.HasAnyFlag(QuestFlags.Daily); }
public bool IsWeekly() { return Flags.HasAnyFlag(QuestFlags.Weekly); }
public bool IsMonthly() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.Monthly); }
public bool IsSeasonal()
{
return (QuestSortID == -(int)QuestSort.Seasonal || QuestSortID == -(int)QuestSort.Special || QuestSortID == -(int)QuestSort.LunarFestival
|| QuestSortID == -(int)QuestSort.Midsummer || QuestSortID == -(int)QuestSort.Brewfest || QuestSortID == -(int)QuestSort.LoveIsInTheAir
|| QuestSortID == -(int)QuestSort.Noblegarden) && !IsRepeatable();
}
public bool IsDailyOrWeekly() { return Flags.HasAnyFlag(QuestFlags.Daily | QuestFlags.Weekly); }
public bool IsDFQuest() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.DfQuest); }
public uint GetRewChoiceItemsCount() { return _rewChoiceItemsCount; }
public uint GetRewItemsCount() { return _rewItemsCount; }
public uint GetRewCurrencyCount() { return _rewCurrencyCount; }
#region Fields
public uint Id;
public QuestType Type;
public int Level;
public uint PackageID;
public int MinLevel;
public int QuestSortID;
public uint QuestInfoID;
public uint SuggestedPlayers;
public uint NextQuestInChain { get; set; }
public uint RewardXPDifficulty;
public float RewardXPMultiplier;
public int RewardMoney;
public uint RewardMoneyDifficulty;
public float RewardMoneyMultiplier;
public uint RewardBonusMoney;
public uint[] RewardDisplaySpell = new uint[SharedConst.QuestRewardDisplaySpellCount];
public uint RewardSpell { get; set; }
public uint RewardHonor;
public uint RewardKillHonor;
public uint RewardArtifactXPDifficulty;
public float RewardArtifactXPMultiplier;
public uint RewardArtifactCategoryID;
public uint SourceItemId { get; set; }
public QuestFlags Flags { get; set; }
public QuestFlagsEx FlagsEx;
public uint[] RewardItemId = new uint[SharedConst.QuestRewardItemCount];
public uint[] RewardItemCount = new uint[SharedConst.QuestRewardItemCount];
public uint[] ItemDrop = new uint[SharedConst.QuestItemDropCount];
public uint[] ItemDropQuantity = new uint[SharedConst.QuestItemDropCount];
public uint[] RewardChoiceItemId = new uint[SharedConst.QuestRewardChoicesCount];
public uint[] RewardChoiceItemCount = new uint[SharedConst.QuestRewardChoicesCount];
public uint[] RewardChoiceItemDisplayId = new uint[SharedConst.QuestRewardChoicesCount];
public uint POIContinent;
public float POIx;
public float POIy;
public uint POIPriority;
public uint RewardTitleId { get; set; }
public int RewardArenaPoints;
public uint RewardSkillId;
public uint RewardSkillPoints;
public uint QuestGiverPortrait;
public uint QuestTurnInPortrait;
public uint[] RewardFactionId = new uint[SharedConst.QuestRewardReputationsCount];
public int[] RewardFactionValue = new int[SharedConst.QuestRewardReputationsCount];
public int[] RewardFactionOverride = new int[SharedConst.QuestRewardReputationsCount];
public uint[] RewardFactionCapIn = new uint[SharedConst.QuestRewardReputationsCount];
public uint RewardReputationMask;
public uint[] RewardCurrencyId = new uint[SharedConst.QuestRewardCurrencyCount];
public uint[] RewardCurrencyCount = new uint[SharedConst.QuestRewardCurrencyCount];
public uint SoundAccept { get; set; }
public uint SoundTurnIn { get; set; }
public uint AreaGroupID;
public uint LimitTime;
public int AllowableRaces { get; set; }
public uint QuestRewardID;
public int Expansion;
public List<QuestObjective> Objectives = new List<QuestObjective>();
public string LogTitle = "";
public string LogDescription = "";
public string QuestDescription = "";
public string AreaDescription = "";
public string PortraitGiverText = "";
public string PortraitGiverName = "";
public string PortraitTurnInText = "";
public string PortraitTurnInName = "";
public string QuestCompletionLog = "";
// quest_detais table
public uint[] DetailsEmote = new uint[SharedConst.QuestEmoteCount];
public uint[] DetailsEmoteDelay = new uint[SharedConst.QuestEmoteCount];
// quest_request_items table
public uint EmoteOnComplete;
public uint EmoteOnIncomplete;
public uint EmoteOnCompleteDelay;
public uint EmoteOnIncompleteDelay;
public string RequestItemsText = "";
// quest_offer_reward table
public uint[] OfferRewardEmote = new uint[SharedConst.QuestEmoteCount];
public uint[] OfferRewardEmoteDelay = new uint[SharedConst.QuestEmoteCount];
public string OfferRewardText = "";
// quest_template_addon table (custom data)
public uint MaxLevel;
public uint AllowableClasses { get; set; }
public uint SourceSpellID { get; set; }
public int PrevQuestId;
public int NextQuestId;
public int ExclusiveGroup;
public uint RewardMailTemplateId { get; set; }
public uint RewardMailDelay { get; set; }
public uint RequiredSkillId;
public uint RequiredSkillPoints;
public uint RequiredMinRepFaction;
public int RequiredMinRepValue;
public uint RequiredMaxRepFaction;
public int RequiredMaxRepValue;
public uint SourceItemIdCount;
public uint RewardMailSenderEntry;
public QuestSpecialFlags SpecialFlags; // custom flags, not sniffed/WDB
public List<int> prevQuests = new List<int>();
public List<uint> prevChainQuests = new List<uint>();
uint _rewChoiceItemsCount;
uint _rewItemsCount;
uint _rewCurrencyCount;
#endregion
}
public class QuestStatusData
{
public QuestStatus Status;
public uint Timer;
public int[] ObjectiveData;
}
public class QuestTemplateLocale
{
public StringArray LogTitle = new StringArray((int)LocaleConstant.Total);
public StringArray LogDescription = new StringArray((int)LocaleConstant.Total);
public StringArray QuestDescription = new StringArray((int)LocaleConstant.Total);
public StringArray AreaDescription = new StringArray((int)LocaleConstant.Total);
public StringArray PortraitGiverText = new StringArray((int)LocaleConstant.Total);
public StringArray PortraitGiverName = new StringArray((int)LocaleConstant.Total);
public StringArray PortraitTurnInText = new StringArray((int)LocaleConstant.Total);
public StringArray PortraitTurnInName = new StringArray((int)LocaleConstant.Total);
public StringArray QuestCompletionLog = new StringArray((int)LocaleConstant.Total);
}
public class QuestRequestItemsLocale
{
public StringArray CompletionText = new StringArray((int)LocaleConstant.Total);
}
public class QuestObjectivesLocale
{
public StringArray Description = new StringArray((int)LocaleConstant.Total);
}
public class QuestOfferRewardLocale
{
public StringArray RewardText = new StringArray((int)LocaleConstant.Total);
}
public class QuestObjective
{
public uint ID;
public uint QuestID;
public QuestObjectiveType Type;
public sbyte StorageIndex;
public int ObjectID;
public int Amount;
public QuestObjectiveFlags Flags;
public uint Flags2;
public float ProgressBarWeight;
public string Description;
public int[] VisualEffects = new int[0];
public bool IsStoringFlag()
{
switch (Type)
{
case QuestObjectiveType.AreaTrigger:
case QuestObjectiveType.WinPetBattleAgainstNpc:
case QuestObjectiveType.DefeatBattlePet:
case QuestObjectiveType.CriteriaTree:
return true;
default:
break;
}
return false;
}
}
}
@@ -0,0 +1,327 @@
/*
* Copyright (C) 2012-2017 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 Framework.Constants;
using Framework.Database;
using Game.Achievements;
using Game.Entities;
using Game.Network;
using Game.Network.Packets;
using System.Collections.Generic;
namespace Game
{
class QuestObjectiveCriteriaManager : CriteriaHandler
{
public QuestObjectiveCriteriaManager(Player owner)
{
_owner = owner;
}
public void CheckAllQuestObjectiveCriteria(Player referencePlayer)
{
// suppress sending packets
for (CriteriaTypes i = 0; i < CriteriaTypes.TotalTypes; ++i)
UpdateCriteria(i, 0, 0, 0, null, referencePlayer);
}
public override void Reset()
{
foreach (var pair in _criteriaProgress)
SendCriteriaProgressRemoved(pair.Key);
_criteriaProgress.Clear();
DeleteFromDB(_owner.GetGUID());
// re-fill data
CheckAllQuestObjectiveCriteria(_owner);
}
public static void DeleteFromDB(ObjectGuid guid)
{
SQLTransaction trans = new SQLTransaction();
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
stmt.AddValue(0, guid.GetCounter());
trans.Append(stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
stmt.AddValue(0, guid.GetCounter());
trans.Append(stmt);
DB.Characters.CommitTransaction(trans);
}
public void LoadFromDB(SQLResult objectiveResult, SQLResult criteriaResult)
{
if (!objectiveResult.IsEmpty())
{
do
{
uint objectiveId = objectiveResult.Read<uint>(0);
QuestObjective objective = Global.ObjectMgr.GetQuestObjective(objectiveId);
if (objective == null)
continue;
_completedObjectives.Add(objectiveId);
} while (objectiveResult.NextRow());
}
if (!criteriaResult.IsEmpty())
{
long now = Time.UnixTime;
do
{
uint criteriaId = criteriaResult.Read<uint>(0);
ulong counter = criteriaResult.Read<ulong>(1);
long date = criteriaResult.Read<uint>(2);
Criteria criteria = Global.CriteriaMgr.GetCriteria(criteriaId);
if (criteria == null)
{
// Removing non-existing criteria data for all characters
Log.outError(LogFilter.Player, "Non-existing quest objective criteria {criteriaId} data has been removed from the table `character_queststatus_objectives_criteria_progress`.");
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_INVALID_QUEST_PROGRESS_CRITERIA);
stmt.AddValue(0, criteriaId);
DB.Characters.Execute(stmt);
continue;
}
if (criteria.Entry.StartTimer != 0 && date + criteria.Entry.StartTimer < now)
continue;
CriteriaProgress progress = new CriteriaProgress();
progress.Counter = counter;
progress.Date = date;
progress.Changed = false;
_criteriaProgress[criteriaId] = progress;
} while (criteriaResult.NextRow());
}
}
public void SaveToDB(SQLTransaction trans)
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
stmt.AddValue(0, _owner.GetGUID().GetCounter());
trans.Append(stmt);
if (!_completedObjectives.Empty())
{
foreach (uint completedObjectiveId in _completedObjectives)
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
stmt.AddValue(0, _owner.GetGUID().GetCounter());
stmt.AddValue(1, completedObjectiveId);
trans.Append(stmt);
}
}
if (!_criteriaProgress.Empty())
{
foreach (var pair in _criteriaProgress)
{
if (!pair.Value.Changed)
continue;
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA);
stmt.AddValue(0, _owner.GetGUID().GetCounter());
stmt.AddValue(1, pair.Key);
trans.Append(stmt);
if (pair.Value.Counter != 0)
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
stmt.AddValue(0, _owner.GetGUID().GetCounter());
stmt.AddValue(1, pair.Key);
stmt.AddValue(2, pair.Value.Counter);
stmt.AddValue(3, (uint)pair.Value.Date);
trans.Append(stmt);
}
pair.Value.Changed = false;
}
}
}
public void ResetCriteria(CriteriaTypes type, ulong miscValue1, ulong miscValue2, bool evenIfCriteriaComplete)
{
Log.outDebug(LogFilter.Player, "QuestObjectiveCriteriaMgr.ResetCriteria({type}, {miscValue1}, {miscValue2})");
// disable for gamemasters with GM-mode enabled
if (_owner.IsGameMaster())
return;
var playerCriteriaList = GetCriteriaByType(type);
foreach (Criteria playerCriteria in playerCriteriaList)
{
if (playerCriteria.Entry.FailEvent != miscValue1 || (playerCriteria.Entry.FailAsset != 0 && playerCriteria.Entry.FailAsset != miscValue2))
continue;
var trees = Global.CriteriaMgr.GetCriteriaTreesByCriteria(playerCriteria.ID);
bool allComplete = true;
foreach (CriteriaTree tree in trees)
{
// don't update already completed criteria if not forced
if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete))
{
allComplete = false;
break;
}
}
if (allComplete)
continue;
RemoveCriteriaProgress(playerCriteria);
}
}
public void ResetCriteriaTree(uint criteriaTreeId)
{
CriteriaTree tree = Global.CriteriaMgr.GetCriteriaTree(criteriaTreeId);
if (tree == null)
return;
CriteriaManager.WalkCriteriaTree(tree, criteriaTree =>
{
RemoveCriteriaProgress(criteriaTree.Criteria);
});
}
public override void SendAllData(Player receiver)
{
foreach (var pair in _criteriaProgress)
{
CriteriaUpdate criteriaUpdate = new CriteriaUpdate();
criteriaUpdate.CriteriaID = pair.Key;
criteriaUpdate.Quantity = pair.Value.Counter;
criteriaUpdate.PlayerGUID = _owner.GetGUID();
criteriaUpdate.Flags = 0;
criteriaUpdate.CurrentTime = pair.Value.Date;
criteriaUpdate.CreationTime = 0;
SendPacket(criteriaUpdate);
}
}
void CompletedObjective(QuestObjective questObjective, Player referencePlayer)
{
// disable for gamemasters with GM-mode enabled
if (_owner.IsGameMaster())
return;
if (HasCompletedObjective(questObjective))
return;
referencePlayer.KillCreditCriteriaTreeObjective(questObjective);
Log.outInfo(LogFilter.Player, "QuestObjectiveCriteriaMgr.CompletedObjective({questObjective.ID}). {GetOwnerInfo()}");
_completedObjectives.Add(questObjective.ID);
}
public bool HasCompletedObjective(QuestObjective questObjective)
{
return _completedObjectives.Contains(questObjective.ID);
}
public override void SendCriteriaUpdate(Criteria criteria, CriteriaProgress progress, uint timeElapsed, bool timedCompleted)
{
CriteriaUpdate criteriaUpdate = new CriteriaUpdate();
criteriaUpdate.CriteriaID = criteria.ID;
criteriaUpdate.Quantity = progress.Counter;
criteriaUpdate.PlayerGUID = _owner.GetGUID();
criteriaUpdate.Flags = 0;
if (criteria.Entry.StartTimer != 0)
criteriaUpdate.Flags = timedCompleted ? 1 : 0u; // 1 is for keeping the counter at 0 in client
criteriaUpdate.CurrentTime = progress.Date;
criteriaUpdate.ElapsedTime = timeElapsed;
criteriaUpdate.CreationTime = 0;
SendPacket(criteriaUpdate);
}
public override void SendCriteriaProgressRemoved(uint criteriaId)
{
CriteriaDeleted criteriaDeleted = new CriteriaDeleted();
criteriaDeleted.CriteriaID = criteriaId;
SendPacket(criteriaDeleted);
}
public override bool CanUpdateCriteriaTree(Criteria criteria, CriteriaTree tree, Player referencePlayer)
{
QuestObjective objective = tree.QuestObjective;
if (objective == null)
return false;
if (HasCompletedObjective(objective))
{
Log.outTrace(LogFilter.Player, "QuestObjectiveCriteriaMgr.CanUpdateCriteriaTree: (Id: {criteria.ID} Type {criteria.Entry.Type} Quest Objective {objective.ID}) Objective already completed");
return false;
}
return base.CanUpdateCriteriaTree(criteria, tree, referencePlayer);
}
public override bool CanCompleteCriteriaTree(CriteriaTree tree)
{
QuestObjective objective = tree.QuestObjective;
if (objective == null)
return false;
return base.CanCompleteCriteriaTree(tree);
}
public override void CompletedCriteriaTree(CriteriaTree tree, Player referencePlayer)
{
QuestObjective objective = tree.QuestObjective;
if (objective == null)
return;
CompletedObjective(objective, referencePlayer);
}
public override void SendPacket(ServerPacket data)
{
_owner.SendPacket(data);
}
public override string GetOwnerInfo()
{
return $"{_owner.GetGUID().ToString()} {_owner.GetName()}";
}
public override List<Criteria> GetCriteriaByType(CriteriaTypes type)
{
return Global.CriteriaMgr.GetQuestObjectiveCriteriaByType(type);
}
Player _owner;
List<uint> _completedObjectives = new List<uint>();
}
}