using CommonAI.ZoneClient; using CommonLang; using CommonLang.IO; using CommonLang.Log; using CommonLang.Vector; using pomelo.area; using pomelo.task; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using XmdsBattleClient.Client; using XmdsBattleClientBot.XmdsBot; namespace XmdsBattleClientBot.Bot { // 游戏服相关 // partial class BotClient { public QuestManager CurrentQuestManager { get; private set; } public TaskUpdatePush LastTaskUpdatePush { get; private set; } private void callback_gs_onTaskUpdatePush(TaskUpdatePush e) { LastTaskUpdatePush = e; CurrentQuestManager.Refresh(e.s2c_data); } public class QuestManager { private readonly BotClient bot; private HashMap mQuests = new HashMap(); public ICollection Quests { get { return mQuests.Values; } } internal QuestManager(BotClient bot) { this.bot = bot; this.Refresh(bot.PlayerData.tasks); } internal void Refresh(Tasks tasks) { if (tasks != null) { foreach (var e in tasks.taskList) { var tq = BotClientManager.GetTaskTemplate(e.templateId); if (tq != null) { QuestData td = mQuests.Get(e.templateId); if (td == null) { td = new QuestData(bot, e.templateId, tq); mQuests.Add(e.templateId, td); } td.UpdateTask(e.progress, e.state, e.leftTime); } } } } public QuestData GetQuest(int templateID) { return mQuests.Get(templateID); } public QuestData SeekExpectTask(BotClient.QuestData.QuestType kind, QuestData.QuestStatus status, QuestData.SeekAction action, bool random = false) { var list = new List(this.Quests); if (random) { CUtils.RandomList(bot.Random, list); } foreach (var qd in list) { if ((kind == QuestData.QuestType.INVALID || qd.Kind == kind) && qd.State == status) { qd.Seek(action); return qd; } } return null; } } public class QuestData { public enum NotiFyStatus : long { progress = 1L << 1, //任务进度 state = 1L << 2, //任务状态 leftTime = 1L << 3, //剩余时间 ALL = long.MaxValue, } //任务状态 public enum QuestStatus : long { NONE = -2, NEW = -1, IN_PROGRESS = 0, CAN_FINISH = 1, DONE = 2, } //任务种类 (NotiFyStatus.kind) public enum QuestType { TRUNK = 0, //主线 BRANCH = 1, //支线 DAILY = 2, //日常任务 RUNNING = 3, //跑环任务 REWARD = 4, //悬赏任务 PVP = 5, //PVP AREA = 6, //区域触发任务 FESTIVAL = 7, //节日任务 INVALID = int.MaxValue, } //任务类型(一个种类可以细分多个类型) public class EventType { public const int INVALID = -1; public const int KillMonster = 1; //杀怪 public const int InterActiveNpc = 2; //与NPC互动 public const int InterActiveItem = 3; //与道具互动 public const int KillCollect = 4; //杀怪拾取道具 public const int Convoy = 5; //护送 public const int Guard = 6; //守护 public const int Area = 7; public const int KillPlayer = 8; public const int FISH = 15; // 钓鱼获得道具 public const int Challenge = 25; public const int ConqueringtheDemons = 26; public const int Steal = 27; public const int RefineSoul = 28; public const int CatchPet = 29; public const int Treasure = 30; public const int GETMEDAL = 31; public const int LEVEL_UP = 32; } private readonly Dictionary mLocalData; private readonly BotClient bot; public BotClient Bot { get { return bot; } } public int TemplateID { get; private set; } public QuestType Kind { get; private set; } public int SubType { get; private set; } public QuestStatus State { get; private set; } public List Progress { get; private set; } public int LeftTime { get; private set; } public int SubmitNpcId { get; private set; } public int AcceptNpcId { get; private set; } public string TargetId { get; private set; } public string Name { get; private set; } internal QuestData(BotClient bot, int templateID, Dictionary fields) { this.bot = bot; this.TemplateID = templateID; this.mLocalData = new Dictionary(fields); this.Kind = (QuestType)GetIntParam("Kind"); this.SubType = GetIntParam("Type"); this.SubmitNpcId = GetIntParam("CompleteNpc"); this.AcceptNpcId = GetIntParam("GiveNpc"); this.TargetId = GetStringParam("TargetID"); this.Name = GetStringParam("Name"); } public override string ToString() { return string.Format("{0}({1})", Name, TemplateID); } internal void UpdateTask(List progress, int state, int leftTime) { long s = 0; if ((int)this.State != state) { s |= (int)NotiFyStatus.state; State = (QuestStatus)(state); } if (this.Progress != progress) { s |= (int)NotiFyStatus.progress; this.Progress = progress; } if (this.LeftTime != leftTime) { s |= (int)NotiFyStatus.leftTime; this.LeftTime = leftTime; } } public int GetIntParam(string name) { if (mLocalData == null) { return -1; } object ret; int ret_int = 0; if (mLocalData.TryGetValue(name, out ret)) { int.TryParse(ret.ToString(), out ret_int); } return ret_int; } public string GetStringParam(string name) { if (mLocalData == null) { return null; } object ret; if (mLocalData.TryGetValue(name, out ret)) { return ret.ToString(); } else { return null; } } //------------------------------------------------------------------------------------------------------------------- public delegate void SeekAction(QuestData quest, SeekInfo info); public class SeekInfo { public readonly QuestData quest; public int areaId; public int pointId; public int npcTemplateID; public bool attack; public Vector2 MoveTo; public string FunID; public bool ShowDetail; public bool NoWay; internal SeekInfo(QuestData quest) { this.quest = quest; } } private void StartSeek(SeekAction action, int areaId, int pointId, int npcTemplateID, string funID, bool attack) { var layer = bot.CurrentZoneLayer; if (layer != null && layer.IsLoaded) { if (areaId == layer.Data.ID) { var point = bot.CurrentZoneLayer.GetFlag(pointId.ToString()); if (point != null) { action.Invoke(this, new SeekInfo(this) { areaId = areaId, pointId = pointId, npcTemplateID = npcTemplateID, attack = attack, MoveTo = new Vector2(point.X, point.Y), }); return; } var npc = bot.CurrentNpcManager.GetNpcByTemplateID(npcTemplateID); if (npc != null) { action.Invoke(this, new SeekInfo(this) { areaId = areaId, pointId = pointId, npcTemplateID = npcTemplateID, attack = attack, MoveTo = new Vector2(npc.X, npc.Y), }); return; } if (!string.IsNullOrEmpty(funID)) { action.Invoke(this, new SeekInfo(this) { FunID = funID, }); return; } action.Invoke(this, new SeekInfo(this) { areaId = areaId, pointId = pointId, npcTemplateID = npcTemplateID, attack = attack, NoWay = true, }); } else { bot.Client.GameSocket.playerHandler.queryLoadWayRequest(areaId, pointId.ToString(), (ex, msg) => { if (ex == null) { var point = bot.CurrentZoneLayer.GetFlag(msg.s2c_pointId); if (point != null) { action.Invoke(this, new SeekInfo(this) { areaId = areaId, pointId = pointId, npcTemplateID = npcTemplateID, attack = attack, MoveTo = new Vector2(point.X, point.Y), }); return; } } action.Invoke(this, new SeekInfo(this) { areaId = areaId, pointId = pointId, npcTemplateID = npcTemplateID, attack = attack, NoWay = true, }); }); } } } private void Goto(SeekAction action, string funID) { action.Invoke(this, new SeekInfo(this) { FunID = funID, }); } private void ShowQuestDetail(SeekAction action) { action.Invoke(this, new SeekInfo(this) { ShowDetail = true, }); } //------------------------------------------------------------------------------------------------------------------- public void Seek(SeekAction action) { if (State == QuestData.QuestStatus.NEW) { int acceptNpcId = GetIntParam("GiveNpc"); if (acceptNpcId > 0) { //int moveType = MoveData.MOVE_TYPE_NPCTALK; int areaId = GetIntParam("StartScene"); int pointId = GetIntParam("StartPoint"); this.StartSeek(action, areaId, pointId, acceptNpcId, null, false); } else { //弹出可接任务详情 // Dictionary p = new Dictionary(); // p.Add("id", TemplateID.ToString()); this.ShowQuestDetail(action); } } else if (State == QuestData.QuestStatus.IN_PROGRESS) { int areaId = GetIntParam("DoScene"); string funId = GetStringParam("FunID"); if (areaId == 0) { if (!string.IsNullOrEmpty(funId)) { // Dictionary p = new Dictionary(); // p.Add("id", funId); this.Goto(action, funId); } else { this.ShowQuestDetail(action); } } else { int pointId = GetIntParam("DoPoint"); int targetId = GetIntParam("TargetID"); //int moveType = 0; bool attack = false; //DataMgr.Instance.UserData.AutoFight = false; if (SubType == QuestData.EventType.InterActiveNpc) { //moveType = MoveData.MOVE_TYPE_NPCTALK; } else if (SubType == EventType.KillMonster || SubType == EventType.KillCollect) { //moveType = MoveData.MOVE_TYPE_ATTACK_MONSTER; attack = true; } this.StartSeek(action, areaId, pointId, targetId, funId, attack); //DataMgr.Instance.UserData.StartSeek(areaId, pointId, moveType, targetId); } } else if (State == QuestData.QuestStatus.CAN_FINISH) { int submitNpcId = GetIntParam("CompleteNpc"); if (submitNpcId > 0) { //DataMgr.Instance.UserData.AutoFight = false; //string targetId = submitNpcId.ToString(); //int moveType = MoveData.MOVE_TYPE_NPCTALK; int areaId = GetIntParam("SubmitScene"); int pointId = GetIntParam("SubmitPoint"); //DataMgr.Instance.UserData.StartSeek(areaId, pointId, moveType, targetId); this.StartSeek(action, areaId, pointId, submitNpcId, null, false); } else { //弹出可接任务详情 // Dictionary p = new Dictionary(); // p.Add("id", TemplateID.ToString()); //EventManager.Fire("Event.ShowQuestDetail", p); this.ShowQuestDetail(action); } } } public string GetTargetString() { string str = GetStringParam("Prompt"); str = str.Replace("%s", GetIntParam("Quantity").ToString()); return str; } public bool IsInterActiveNpc(int npcTemplateId) { return (SubType == QuestData.EventType.InterActiveNpc && State == QuestData.QuestStatus.IN_PROGRESS && GetIntParam("TargetID") == npcTemplateId); } public string GetFormatProgress() { int total = GetIntParam("Quantity"); //progress为0和Quantity为0表示没有进度 if (Progress[0] == 0 && total == 0 && State != QuestStatus.IN_PROGRESS || (SubType == EventType.InterActiveNpc && total == 1)) { return null; } else { string format = "({0}/{1})"; string ret = string.Format(format, this.Progress, total); return ret; } } } } }