BotClient.Task.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. using CommonAI.ZoneClient;
  2. using CommonLang;
  3. using CommonLang.IO;
  4. using CommonLang.Log;
  5. using CommonLang.Vector;
  6. using pomelo.area;
  7. using pomelo.task;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading;
  14. using XmdsBattleClient.Client;
  15. using XmdsBattleClientBot.XmdsBot;
  16. namespace XmdsBattleClientBot.Bot
  17. {
  18. // 游戏服相关 //
  19. partial class BotClient
  20. {
  21. public QuestManager CurrentQuestManager { get; private set; }
  22. public TaskUpdatePush LastTaskUpdatePush { get; private set; }
  23. private void callback_gs_onTaskUpdatePush(TaskUpdatePush e)
  24. {
  25. LastTaskUpdatePush = e;
  26. CurrentQuestManager.Refresh(e.s2c_data);
  27. }
  28. public class QuestManager
  29. {
  30. private readonly BotClient bot;
  31. private HashMap<int, QuestData> mQuests = new HashMap<int, QuestData>();
  32. public ICollection<QuestData> Quests { get { return mQuests.Values; } }
  33. internal QuestManager(BotClient bot)
  34. {
  35. this.bot = bot;
  36. this.Refresh(bot.PlayerData.tasks);
  37. }
  38. internal void Refresh(Tasks tasks)
  39. {
  40. if (tasks != null)
  41. {
  42. foreach (var e in tasks.taskList)
  43. {
  44. var tq = BotClientManager.GetTaskTemplate(e.templateId);
  45. if (tq != null)
  46. {
  47. QuestData td = mQuests.Get(e.templateId);
  48. if (td == null)
  49. {
  50. td = new QuestData(bot, e.templateId, tq);
  51. mQuests.Add(e.templateId, td);
  52. }
  53. td.UpdateTask(e.progress, e.state, e.leftTime);
  54. }
  55. }
  56. }
  57. }
  58. public QuestData GetQuest(int templateID)
  59. {
  60. return mQuests.Get(templateID);
  61. }
  62. public QuestData SeekExpectTask(BotClient.QuestData.QuestType kind, QuestData.QuestStatus status, QuestData.SeekAction action, bool random = false)
  63. {
  64. var list = new List<QuestData>(this.Quests);
  65. if (random)
  66. {
  67. CUtils.RandomList<QuestData>(bot.Random, list);
  68. }
  69. foreach (var qd in list)
  70. {
  71. if ((kind == QuestData.QuestType.INVALID || qd.Kind == kind) && qd.State == status)
  72. {
  73. qd.Seek(action);
  74. return qd;
  75. }
  76. }
  77. return null;
  78. }
  79. }
  80. public class QuestData
  81. {
  82. public enum NotiFyStatus : long
  83. {
  84. progress = 1L << 1, //任务进度
  85. state = 1L << 2, //任务状态
  86. leftTime = 1L << 3, //剩余时间
  87. ALL = long.MaxValue,
  88. }
  89. //任务状态
  90. public enum QuestStatus : long
  91. {
  92. NONE = -2,
  93. NEW = -1,
  94. IN_PROGRESS = 0,
  95. CAN_FINISH = 1,
  96. DONE = 2,
  97. }
  98. //任务种类 (NotiFyStatus.kind)
  99. public enum QuestType
  100. {
  101. TRUNK = 0, //主线
  102. BRANCH = 1, //支线
  103. DAILY = 2, //日常任务
  104. RUNNING = 3, //跑环任务
  105. REWARD = 4, //悬赏任务
  106. PVP = 5, //PVP
  107. AREA = 6, //区域触发任务
  108. FESTIVAL = 7, //节日任务
  109. INVALID = int.MaxValue,
  110. }
  111. //任务类型(一个种类可以细分多个类型)
  112. public class EventType
  113. {
  114. public const int INVALID = -1;
  115. public const int KillMonster = 1; //杀怪
  116. public const int InterActiveNpc = 2; //与NPC互动
  117. public const int InterActiveItem = 3; //与道具互动
  118. public const int KillCollect = 4; //杀怪拾取道具
  119. public const int Convoy = 5; //护送
  120. public const int Guard = 6; //守护
  121. public const int Area = 7;
  122. public const int KillPlayer = 8;
  123. public const int FISH = 15; // 钓鱼获得道具
  124. public const int Challenge = 25;
  125. public const int ConqueringtheDemons = 26;
  126. public const int Steal = 27;
  127. public const int RefineSoul = 28;
  128. public const int CatchPet = 29;
  129. public const int Treasure = 30;
  130. public const int GETMEDAL = 31;
  131. public const int LEVEL_UP = 32;
  132. }
  133. private readonly Dictionary<string, object> mLocalData;
  134. private readonly BotClient bot;
  135. public BotClient Bot { get { return bot; } }
  136. public int TemplateID { get; private set; }
  137. public QuestType Kind { get; private set; }
  138. public int SubType { get; private set; }
  139. public QuestStatus State { get; private set; }
  140. public List<int> Progress { get; private set; }
  141. public int LeftTime { get; private set; }
  142. public int SubmitNpcId { get; private set; }
  143. public int AcceptNpcId { get; private set; }
  144. public string TargetId { get; private set; }
  145. public string Name { get; private set; }
  146. internal QuestData(BotClient bot, int templateID, Dictionary<string, object> fields)
  147. {
  148. this.bot = bot;
  149. this.TemplateID = templateID;
  150. this.mLocalData = new Dictionary<string, object>(fields);
  151. this.Kind = (QuestType)GetIntParam("Kind");
  152. this.SubType = GetIntParam("Type");
  153. this.SubmitNpcId = GetIntParam("CompleteNpc");
  154. this.AcceptNpcId = GetIntParam("GiveNpc");
  155. this.TargetId = GetStringParam("TargetID");
  156. this.Name = GetStringParam("Name");
  157. }
  158. public override string ToString()
  159. {
  160. return string.Format("{0}({1})", Name, TemplateID);
  161. }
  162. internal void UpdateTask(List<int> progress, int state, int leftTime)
  163. {
  164. long s = 0;
  165. if ((int)this.State != state)
  166. {
  167. s |= (int)NotiFyStatus.state;
  168. State = (QuestStatus)(state);
  169. }
  170. if (this.Progress != progress)
  171. {
  172. s |= (int)NotiFyStatus.progress;
  173. this.Progress = progress;
  174. }
  175. if (this.LeftTime != leftTime)
  176. {
  177. s |= (int)NotiFyStatus.leftTime;
  178. this.LeftTime = leftTime;
  179. }
  180. }
  181. public int GetIntParam(string name)
  182. {
  183. if (mLocalData == null)
  184. {
  185. return -1;
  186. }
  187. object ret;
  188. int ret_int = 0;
  189. if (mLocalData.TryGetValue(name, out ret))
  190. {
  191. int.TryParse(ret.ToString(), out ret_int);
  192. }
  193. return ret_int;
  194. }
  195. public string GetStringParam(string name)
  196. {
  197. if (mLocalData == null)
  198. {
  199. return null;
  200. }
  201. object ret;
  202. if (mLocalData.TryGetValue(name, out ret))
  203. {
  204. return ret.ToString();
  205. }
  206. else
  207. {
  208. return null;
  209. }
  210. }
  211. //-------------------------------------------------------------------------------------------------------------------
  212. public delegate void SeekAction(QuestData quest, SeekInfo info);
  213. public class SeekInfo
  214. {
  215. public readonly QuestData quest;
  216. public int areaId;
  217. public int pointId;
  218. public int npcTemplateID;
  219. public bool attack;
  220. public Vector2 MoveTo;
  221. public string FunID;
  222. public bool ShowDetail;
  223. public bool NoWay;
  224. internal SeekInfo(QuestData quest)
  225. {
  226. this.quest = quest;
  227. }
  228. }
  229. private void StartSeek(SeekAction action, int areaId, int pointId, int npcTemplateID, string funID, bool attack)
  230. {
  231. var layer = bot.CurrentZoneLayer;
  232. if (layer != null && layer.IsLoaded)
  233. {
  234. if (areaId == layer.Data.ID)
  235. {
  236. var point = bot.CurrentZoneLayer.GetFlag<ZoneEditorPoint>(pointId.ToString());
  237. if (point != null)
  238. {
  239. action.Invoke(this, new SeekInfo(this)
  240. {
  241. areaId = areaId,
  242. pointId = pointId,
  243. npcTemplateID = npcTemplateID,
  244. attack = attack,
  245. MoveTo = new Vector2(point.X, point.Y),
  246. });
  247. return;
  248. }
  249. var npc = bot.CurrentNpcManager.GetNpcByTemplateID(npcTemplateID);
  250. if (npc != null)
  251. {
  252. action.Invoke(this, new SeekInfo(this)
  253. {
  254. areaId = areaId,
  255. pointId = pointId,
  256. npcTemplateID = npcTemplateID,
  257. attack = attack,
  258. MoveTo = new Vector2(npc.X, npc.Y),
  259. });
  260. return;
  261. }
  262. if (!string.IsNullOrEmpty(funID))
  263. {
  264. action.Invoke(this, new SeekInfo(this) { FunID = funID, });
  265. return;
  266. }
  267. action.Invoke(this, new SeekInfo(this)
  268. {
  269. areaId = areaId,
  270. pointId = pointId,
  271. npcTemplateID = npcTemplateID,
  272. attack = attack,
  273. NoWay = true,
  274. });
  275. }
  276. else
  277. {
  278. bot.Client.GameSocket.playerHandler.queryLoadWayRequest(areaId, pointId.ToString(), (ex, msg) =>
  279. {
  280. if (ex == null)
  281. {
  282. var point = bot.CurrentZoneLayer.GetFlag(msg.s2c_pointId);
  283. if (point != null)
  284. {
  285. action.Invoke(this, new SeekInfo(this)
  286. {
  287. areaId = areaId,
  288. pointId = pointId,
  289. npcTemplateID = npcTemplateID,
  290. attack = attack,
  291. MoveTo = new Vector2(point.X, point.Y),
  292. });
  293. return;
  294. }
  295. }
  296. action.Invoke(this, new SeekInfo(this)
  297. {
  298. areaId = areaId,
  299. pointId = pointId,
  300. npcTemplateID = npcTemplateID,
  301. attack = attack,
  302. NoWay = true,
  303. });
  304. });
  305. }
  306. }
  307. }
  308. private void Goto(SeekAction action, string funID)
  309. {
  310. action.Invoke(this, new SeekInfo(this) { FunID = funID, });
  311. }
  312. private void ShowQuestDetail(SeekAction action)
  313. {
  314. action.Invoke(this, new SeekInfo(this) { ShowDetail = true, });
  315. }
  316. //-------------------------------------------------------------------------------------------------------------------
  317. public void Seek(SeekAction action)
  318. {
  319. if (State == QuestData.QuestStatus.NEW)
  320. {
  321. int acceptNpcId = GetIntParam("GiveNpc");
  322. if (acceptNpcId > 0)
  323. {
  324. //int moveType = MoveData.MOVE_TYPE_NPCTALK;
  325. int areaId = GetIntParam("StartScene");
  326. int pointId = GetIntParam("StartPoint");
  327. this.StartSeek(action, areaId, pointId, acceptNpcId, null, false);
  328. }
  329. else
  330. {
  331. //弹出可接任务详情
  332. // Dictionary<string, string> p = new Dictionary<string, string>();
  333. // p.Add("id", TemplateID.ToString());
  334. this.ShowQuestDetail(action);
  335. }
  336. }
  337. else if (State == QuestData.QuestStatus.IN_PROGRESS)
  338. {
  339. int areaId = GetIntParam("DoScene");
  340. string funId = GetStringParam("FunID");
  341. if (areaId == 0)
  342. {
  343. if (!string.IsNullOrEmpty(funId))
  344. {
  345. // Dictionary<string, string> p = new Dictionary<string, string>();
  346. // p.Add("id", funId);
  347. this.Goto(action, funId);
  348. }
  349. else
  350. {
  351. this.ShowQuestDetail(action);
  352. }
  353. }
  354. else
  355. {
  356. int pointId = GetIntParam("DoPoint");
  357. int targetId = GetIntParam("TargetID");
  358. //int moveType = 0;
  359. bool attack = false;
  360. //DataMgr.Instance.UserData.AutoFight = false;
  361. if (SubType == QuestData.EventType.InterActiveNpc)
  362. {
  363. //moveType = MoveData.MOVE_TYPE_NPCTALK;
  364. }
  365. else if (SubType == EventType.KillMonster || SubType == EventType.KillCollect)
  366. {
  367. //moveType = MoveData.MOVE_TYPE_ATTACK_MONSTER;
  368. attack = true;
  369. }
  370. this.StartSeek(action, areaId, pointId, targetId, funId, attack);
  371. //DataMgr.Instance.UserData.StartSeek(areaId, pointId, moveType, targetId);
  372. }
  373. }
  374. else if (State == QuestData.QuestStatus.CAN_FINISH)
  375. {
  376. int submitNpcId = GetIntParam("CompleteNpc");
  377. if (submitNpcId > 0)
  378. {
  379. //DataMgr.Instance.UserData.AutoFight = false;
  380. //string targetId = submitNpcId.ToString();
  381. //int moveType = MoveData.MOVE_TYPE_NPCTALK;
  382. int areaId = GetIntParam("SubmitScene");
  383. int pointId = GetIntParam("SubmitPoint");
  384. //DataMgr.Instance.UserData.StartSeek(areaId, pointId, moveType, targetId);
  385. this.StartSeek(action, areaId, pointId, submitNpcId, null, false);
  386. }
  387. else
  388. {
  389. //弹出可接任务详情
  390. // Dictionary<string, string> p = new Dictionary<string, string>();
  391. // p.Add("id", TemplateID.ToString());
  392. //EventManager.Fire("Event.ShowQuestDetail", p);
  393. this.ShowQuestDetail(action);
  394. }
  395. }
  396. }
  397. public string GetTargetString()
  398. {
  399. string str = GetStringParam("Prompt");
  400. str = str.Replace("%s", GetIntParam("Quantity").ToString());
  401. return str;
  402. }
  403. public bool IsInterActiveNpc(int npcTemplateId)
  404. {
  405. return (SubType == QuestData.EventType.InterActiveNpc &&
  406. State == QuestData.QuestStatus.IN_PROGRESS &&
  407. GetIntParam("TargetID") == npcTemplateId);
  408. }
  409. public string GetFormatProgress()
  410. {
  411. int total = GetIntParam("Quantity");
  412. //progress为0和Quantity为0表示没有进度
  413. if (Progress[0] == 0 && total == 0 && State != QuestStatus.IN_PROGRESS ||
  414. (SubType == EventType.InterActiveNpc && total == 1))
  415. {
  416. return null;
  417. }
  418. else
  419. {
  420. string format = "({0}/{1})";
  421. string ret = string.Format(format, this.Progress, total);
  422. return ret;
  423. }
  424. }
  425. }
  426. }
  427. }