Core/AI: Implemented conversation ai

Port From (https://github.com/TrinityCore/TrinityCore/commit/309ba22a15e5e0b4321b99f7157ccb18e0adc8dd)
This commit is contained in:
Hondacrx
2025-05-19 17:23:36 -04:00
parent 4f63e81373
commit e44861a629
10 changed files with 160 additions and 126 deletions
+24 -5
View File
@@ -2,6 +2,7 @@
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Constants;
using Game.AI;
using Game.DataStorage;
using Game.Maps;
using Game.Networking;
@@ -43,6 +44,8 @@ namespace Game.Entities
//- Remove the Conversation from the accessor and from all lists of objects in world
if (IsInWorld)
{
_ai.OnRemove();
base.RemoveFromWorld();
GetMap().GetObjectsStore().Remove(GetGUID());
}
@@ -50,7 +53,7 @@ namespace Game.Entities
public override void Update(uint diff)
{
Global.ScriptMgr.OnConversationUpdate(this, diff);
_ai.OnUpdate(diff);
if (GetDuration() > TimeSpan.FromMilliseconds(diff))
{
@@ -116,13 +119,13 @@ namespace Game.Entities
SetEntry(conversationEntry);
SetObjectScale(1.0f);
AI_Initialize();
_textureKitId = conversationTemplate.TextureKitId;
foreach (var actor in conversationTemplate.Actors)
new ConversationActorFillVisitor(this, creator, map, actor).Invoke(actor);
Global.ScriptMgr.OnConversationCreate(this, creator);
List<ConversationLine> lines = new();
foreach (ConversationLineTemplate line in conversationTemplate.Lines)
{
@@ -165,7 +168,7 @@ namespace Game.Entities
// conversations are despawned 5-20s after LastLineEndTime
_duration += TimeSpan.FromSeconds(10);
Global.ScriptMgr.OnConversationCreate(this, creator);
_ai.OnCreate(creator);
}
public bool Start()
@@ -193,7 +196,7 @@ namespace Game.Entities
if (!GetMap().AddToMap(this))
return false;
Global.ScriptMgr.OnConversationStart(this);
_ai.OnStart();
return true;
}
@@ -284,6 +287,20 @@ namespace Game.Entities
return actor.ToCreature();
}
void AI_Initialize()
{
AI_Destroy();
_ai = AISelector.SelectConversationAI(this);
_ai.OnInitialize();
}
void AI_Destroy()
{
_ai = null;
}
public ConversationAI GetAI() { return _ai; }
public uint GetScriptId()
{
return Global.ConversationDataStorage.GetConversationTemplate(GetEntry()).ScriptId;
@@ -363,6 +380,8 @@ namespace Game.Entities
Dictionary<(Locale locale, uint lineId), TimeSpan> _lineStartTimes = new();
TimeSpan[] _lastLineEndTimes = new TimeSpan[(int)Locale.Total];
ConversationAI _ai;
class ValuesUpdateForPlayerWithMaskSender : IDoWork<Player>
{
Conversation Owner;
+11 -25
View File
@@ -632,7 +632,8 @@ namespace Game.Entities
stmt.AddValue(5, homebind.GetPositionZ());
stmt.AddValue(6, homebind.GetOrientation());
DB.Characters.Execute(stmt);
};
}
;
if (!ok && HasAtLoginFlag(AtLoginFlags.FirstLogin))
{
@@ -869,11 +870,7 @@ namespace Game.Entities
// Skip loading special quests - they are also added to rewarded quests but only once and remain there forever
// instead add them separately from load daily/weekly/monthly/seasonal
if (!quest.IsDailyOrWeekly() && !quest.IsMonthly() && !quest.IsSeasonal())
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
}
SetQuestCompletedBit(quest_id, true);
for (uint i = 0; i < quest.GetRewChoiceItemsCount(); ++i)
GetSession().GetCollectionMgr().AddItemAppearance(quest.RewardChoiceItemId[i]);
@@ -929,9 +926,7 @@ namespace Game.Entities
continue;
AddDynamicUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.DailyQuestsCompleted), quest_id);
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
SetQuestCompletedBit(quest_id, true);
Log.outDebug(LogFilter.Player, "Daily quest ({0}) cooldown for player (GUID: {1})", quest_id, GetGUID().ToString());
}
@@ -954,9 +949,7 @@ namespace Game.Entities
continue;
m_weeklyquests.Add(quest_id);
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
SetQuestCompletedBit(quest_id, true);
Log.outDebug(LogFilter.Player, "Weekly quest {0} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString());
}
@@ -984,10 +977,7 @@ namespace Game.Entities
m_seasonalquests[event_id] = new();
m_seasonalquests[event_id][quest_id] = completedTime;
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
SetQuestCompletedBit(quest_id, true);
Log.outDebug(LogFilter.Player, "Seasonal quest {0} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString());
}
@@ -996,12 +986,8 @@ namespace Game.Entities
m_SeasonalQuestChanged = false;
}
void _LoadMonthlyQuestStatus()
void _LoadMonthlyQuestStatus(SQLResult result)
{
PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.SEL_CHARACTER_QUESTSTATUS_MONTHLY);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult result = DB.Characters.Query(stmt);
m_monthlyquests.Clear();
if (!result.IsEmpty())
@@ -1014,9 +1000,7 @@ namespace Game.Entities
continue;
m_monthlyquests.Add(quest_id);
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(quest_id);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
SetQuestCompletedBit(quest_id, true);
Log.outDebug(LogFilter.Player, "Monthly quest {0} cooldown for player (GUID: {1})", quest_id, GetGUID().ToString());
}
@@ -3447,6 +3431,7 @@ namespace Game.Entities
_LoadDailyQuestStatus(holder.GetResult(PlayerLoginQueryLoad.DailyQuestStatus));
_LoadWeeklyQuestStatus(holder.GetResult(PlayerLoginQueryLoad.WeeklyQuestStatus));
_LoadSeasonalQuestStatus(holder.GetResult(PlayerLoginQueryLoad.SeasonalQuestStatus));
_LoadMonthlyQuestStatus(holder.GetResult(PlayerLoginQueryLoad.MonthlyQuestStatus));
_LoadRandomBGStatus(holder.GetResult(PlayerLoginQueryLoad.RandomBg));
// after spell and quest load
@@ -3705,7 +3690,8 @@ namespace Game.Entities
stmt.AddValue(0, GetGUID().GetCounter());
characterTransaction.Append(stmt);
static float finiteAlways(float f) { return float.IsFinite(f) ? f : 0.0f; };
static float finiteAlways(float f) { return float.IsFinite(f) ? f : 0.0f; }
;
if (create)
{
+9 -28
View File
@@ -156,11 +156,7 @@ namespace Game.Entities
public void DailyReset()
{
foreach (uint questId in m_activePlayerData.DailyQuestsCompleted)
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, false);
}
SetQuestCompletedBit(questId, false);
DailyQuestsReset dailyQuestsReset = new();
dailyQuestsReset.Count = m_activePlayerData.DailyQuestsCompleted.Size();
@@ -207,11 +203,7 @@ namespace Game.Entities
return;
foreach (uint questId in m_weeklyquests)
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, false);
}
SetQuestCompletedBit(questId, false);
for (ushort slot = 0; slot < SharedConst.MaxQuestLogSize; ++slot)
{
@@ -253,9 +245,7 @@ namespace Game.Entities
{
if (completedTime < eventStartTime)
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, false);
SetQuestCompletedBit(questId, false);
eventList.Remove(questId);
}
@@ -271,11 +261,7 @@ namespace Game.Entities
return;
foreach (uint questId in m_monthlyquests)
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, false);
}
SetQuestCompletedBit(questId, false);
m_monthlyquests.Clear();
// DB data deleted in caller
@@ -1203,9 +1189,7 @@ namespace Game.Entities
// make full db save
SaveToDB(false);
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
SetQuestCompletedBit(questId, true);
if (quest.HasFlag(QuestFlags.Pvp))
{
@@ -1256,9 +1240,7 @@ namespace Game.Entities
m_RewardedQuests.Add(questId);
m_RewardedQuestsSave[questId] = QuestSaveType.Default;
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, true);
SetQuestCompletedBit(questId, true);
}
public void FailQuest(uint questId)
@@ -1952,9 +1934,7 @@ namespace Game.Entities
m_RewardedQuestsSave[questId] = QuestSaveType.ForceDelete;
}
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit != 0)
SetQuestCompletedBit(questBit, false);
SetQuestCompletedBit(questId, false);
// Remove seasonal quest also
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
@@ -2429,8 +2409,9 @@ namespace Game.Entities
return (m_activePlayerData.BitVectors.GetValue().Values[(int)PlayerDataFlag.CharacterQuestCompletedIndex].Values[fieldOffset] & flag) != 0;
}
void SetQuestCompletedBit(uint questBit, bool completed)
void SetQuestCompletedBit(uint questId, bool completed)
{
uint questBit = Global.DB2Mgr.GetQuestUniqueBitFlag(questId);
if (questBit == 0)
return;