Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

TurnIn.lua 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. --[[
  2. Turn-In Mod
  3. version 2.1
  4. Authored by Ian Friedman
  5. Sabindeus of Smolderthorn (Alliance)
  6. The repeatable quest turn in automating machine.
  7. Thanks to Arcanemagus of Hyjal for extra bug fixes and coding input
  8. ]]
  9. TI_VersionString = "2.0";
  10. local TI_slashtable;
  11. TI_gossipclosed = false;
  12. TI_LoadedNPCIndex = 0;
  13. TI_activenumber = 1;
  14. TI_availnumber = 1;
  15. TI_specnum = 0;
  16. TI_gossipopts = {};
  17. TI_TempNPCList = {};
  18. TI_TempNPCListMaxSize = 5;
  19. TI_NPCInQuestion = nil;
  20. local TI_GossipDefaults = {
  21. availquest ="Available Quests",
  22. activequest = "Active Quests",
  23. gossip = "Gossip",
  24. vendor = "Vendor",
  25. taxi = "Taxi",
  26. trainer = "Trainer",
  27. battlemaster = "Battlemaster",
  28. binder = "Hearthstone Binder",
  29. healer = "Spirit Healer",
  30. banker = "Bank"
  31. };
  32. local TI_FunctionList = {
  33. g = {
  34. availquest = C_GossipInfo.SelectActiveQuest,
  35. activequest = C_GossipInfo.SelectAvailableQuest,
  36. default = C_GossipInfo.SelectOption
  37. },
  38. q = {
  39. availquest = SelectAvailableQuest,
  40. activequest = SelectActiveQuest
  41. }
  42. };
  43. local TI_DefaultStatus = {
  44. state = false,
  45. version = TI_VersionString,
  46. options = {},
  47. debugstate = false,
  48. usedefault=true,
  49. autoadd=false
  50. };
  51. local TI_events = {
  52. "GOSSIP_SHOW",
  53. "GOSSIP_CLOSED",
  54. "QUEST_DETAIL",
  55. "QUEST_COMPLETE",
  56. "QUEST_PROGRESS",
  57. "QUEST_GREETING",
  58. "QUEST_FINISHED"
  59. };
  60. TI_TempNPCList = {};
  61. function TI_message(...)
  62. local x = {...};
  63. for k,v in pairs(x) do
  64. DEFAULT_CHAT_FRAME:AddMessage(tostring(v));
  65. end
  66. end
  67. function TI_debug(...)
  68. if(TI_status.debugstate) then
  69. TI_message(...)
  70. end
  71. end
  72. function TI_OnLoad()
  73. SlashCmdList["TI"]=TI_SlashCmdHandler;
  74. SLASH_TI1="/turnin";
  75. SLASH_TI2="/ti";
  76. tinsert(UISpecialFrames,"TI_OptionsFrame");
  77. TI_message("Turn In loaded");
  78. TI_slashtable = {};
  79. TI_gossipopts = {};
  80. TI_gossipclosed = false;
  81. TurnIn:RegisterEvent("VARIABLES_LOADED");
  82. TI_activenumber = 1;
  83. TI_availnumber = 1;
  84. TI_specnum = 0;
  85. StaticPopupDialogs["TI_NPCINQUESTION"] = {
  86. text = "The NPC %s is already in your NPC Database. Do you wish to replace his gossip options with the current ones? (Note: This will overwrite your settings for this NPC.)",
  87. button1 = "Yes",
  88. button2 = "No",
  89. OnAccept = function()
  90. TI_AddNPCToList(TI_NPCInQuestion.list, TI_NPCInQuestion.name, true);
  91. end,
  92. timeout=0,
  93. whileDead = 1,
  94. hideOnEscape = 1
  95. };
  96. end
  97. function TI_VarInit()
  98. if(not TI_status or TI_status.version ~= TI_VersionString) then
  99. TI_status = TI_copyTable(TI_DefaultStatus);
  100. TI_OptionsInit();
  101. end
  102. if(not TI_status.options or #TI_status.options == 0) then
  103. TI_OptionsInit();
  104. end
  105. if(not TI_NPCDB) then
  106. TI_NPCDB = {};
  107. end
  108. if(not TI_NPCIndex) then
  109. TI_NPCIndexGenerate();
  110. end
  111. TI_PopulateOptions("vars loaded");
  112. end
  113. function TI_OptionsInit()
  114. TI_status.options = {};
  115. for k,v in pairs(TI_GossipDefaults) do
  116. local temp = {};
  117. temp.name = v;
  118. temp.type = k;
  119. temp.state = false;
  120. table.insert(TI_status.options, temp);
  121. end
  122. end
  123. function TI_NPCIndexGenerate()
  124. TI_NPCIndex = {};
  125. for k,v in pairs(TI_NPCDB) do
  126. table.insert(TI_NPCIndex, k);
  127. end
  128. table.sort(TI_NPCIndex);
  129. end
  130. function TI_LoadEvents()
  131. for k,v in pairs(TI_events) do
  132. TurnIn:RegisterEvent(v);
  133. end
  134. end
  135. function TI_ResetPointers()
  136. TI_activenumber = 1;
  137. TI_availnumber = 1;
  138. TI_specnum = 0;
  139. end
  140. function TI_UnloadEvents()
  141. for k,v in pairs(TI_events) do
  142. TurnIn:UnregisterEvent(v);
  143. end
  144. end
  145. function TI_Switch(state)
  146. if(state=="on") then
  147. TI_status.state = true;
  148. TI_LoadEvents();
  149. TI_message("Turn In On");
  150. elseif(state=="off") then
  151. TI_ResetPointers();
  152. TI_status.state = false;
  153. TI_UnloadEvents();
  154. TI_message("Turn In Off");
  155. elseif(state=="toggle") then
  156. if(TI_status.state) then
  157. TI_Switch("off");
  158. else
  159. TI_Switch("on");
  160. end
  161. end
  162. TI_StatusIndicatorUpdate();
  163. end
  164. function TI_SlashCmdHandler(cmd)
  165. cmdlist = {strsplit(" ", cmd)};
  166. local commands = {
  167. on = function ()
  168. TI_Switch("on");
  169. end,
  170. off = function ()
  171. TI_Switch("off");
  172. end,
  173. toggle = function ()
  174. TI_Switch("toggle");
  175. end,
  176. status = function ()
  177. if(TI_status.state) then
  178. TI_message("Turn In On");
  179. else
  180. TI_message("Turn In Off");
  181. end
  182. end,
  183. window = function ()
  184. TI_OptionsFrame:Show();
  185. end,
  186. config = function ()
  187. TI_OptionsFrame:Show();
  188. end,
  189. recent = function ()
  190. TI_TempNPCListWindow:Show();
  191. end,
  192. debug = function ()
  193. if(TI_status.debugstate) then
  194. TI_status.debugstate = false;
  195. TI_message("debug mode off");
  196. else
  197. TI_status.debugstate = true;
  198. TI_message("debug mode on");
  199. end
  200. end
  201. };
  202. if(commands[cmdlist[1]]) then
  203. commands[cmdlist[1]](cmdlist[2], cmdlist[3], cmdlist[4]);
  204. else
  205. TI_message("Turn In 2.1 Help", "--------------", "/ti on - turns Turn In on", "/ti off - turns Turn In off", "/ti toggle - toggles Turn In on or off", "/ti window - shows the options window", "/ti recent - shows the recently visited NPCs");
  206. end
  207. end
  208. function TI_IsNPCOn(npcname, type)
  209. local opton = false;
  210. if(type ~= nil) then
  211. for k,v in pairs(TI_status.options) do
  212. if(v.type == type and v.state == true) then
  213. opton = true;
  214. end
  215. end
  216. else
  217. opton = true;
  218. end
  219. if(TI_NPCDB[npcname] == nil and TI_status.usedefault == true and opton == true) then
  220. TI_debug("case 1");
  221. return true;
  222. elseif(TI_NPCDB[npcname] ~= nil and TI_NPCDB[npcname].state) then
  223. TI_debug("case 2");
  224. return true;
  225. elseif(TI_NPCDB[npcname] ~= nil and TI_status.usedefault == true and not TI_NPCDB[npcname].state and opton == true) then
  226. TI_debug("case 4");
  227. return true;
  228. else
  229. TI_debug("case 3");
  230. return false;
  231. end
  232. end
  233. function TI_OnEvent(self, event, ...)
  234. if(event == "VARIABLES_LOADED") then
  235. TI_VarInit();
  236. if(TI_status.state) then
  237. TI_LoadEvents();
  238. end
  239. end
  240. if(TI_status.state and not IsShiftKeyDown()) then
  241. if(event == "QUEST_GREETING") then
  242. TI_debug("Quest Greeting");
  243. TI_lastquestframe = "greeting";
  244. if(QuestFrame:IsVisible()) then
  245. if(TI_gossipclosed) then
  246. TI_debug("resetting pointers");
  247. TI_gossipclosed = false;
  248. TI_ResetPointers();
  249. end
  250. TI_HandleGossipWindow("q");
  251. end
  252. end
  253. if(event == "GOSSIP_SHOW") then
  254. TI_debug("Gossip Show");
  255. if(GossipFrame:IsVisible()) then
  256. if(TI_gossipclosed) then
  257. TI_debug("resetting pointers");
  258. TI_gossipclosed = false;
  259. TI_ResetPointers();
  260. end
  261. TI_HandleGossipWindow("g");
  262. end
  263. end
  264. if(event == "GOSSIP_CLOSED") then
  265. TI_debug("Gossip Closed");
  266. if(not GossipFrame:IsVisible()) then
  267. TI_gossipclosed = true;
  268. end;
  269. end
  270. if(event == "QUEST_COMPLETE") then
  271. TI_debug("Quest Complete");
  272. if(TI_IsNPCOn(UnitName("npc"), "activequest")) then
  273. if(not (GetNumQuestChoices() > 1)) then
  274. GetQuestReward(1);
  275. end
  276. end
  277. TI_ResetPointers();
  278. end
  279. if(event == "QUEST_PROGRESS") then
  280. TI_debug("Quest Progress");
  281. TI_gossipclosed = false;
  282. TI_lastquestframe = "progress";
  283. TI_HandleQuestProgress();
  284. end
  285. if(event == "QUEST_DETAIL") then
  286. TI_debug("Quest Detail");
  287. TI_gossipclosed = false;
  288. if(TI_IsNPCOn(UnitName("npc"), "availquest")) then
  289. TI_HandleAcceptQuest();
  290. end
  291. TI_ResetPointers();
  292. end
  293. if(event == "QUEST_FINISHED") then
  294. TI_debug("Quest Finished");
  295. if(not QuestFrame:IsVisible() and TI_lastquestframe == "greeting") then
  296. TI_debug("looks like the quest frame closed, resetting pointers on next open");
  297. TI_gossipclosed = true;
  298. end
  299. end
  300. end
  301. end
  302. function TI_HandleAcceptQuest()
  303. --QuestInfoFadingFrame_OnUpdate(QuestInfoFadingFrame, 1); -- does not exist anymore in 6.0
  304. QuestDetailAcceptButton_OnClick();
  305. end
  306. function TI_HandleQuestProgress()
  307. local questname = GetTitleText();
  308. local npcname = UnitName("npc");
  309. if(QuestFrame:IsVisible()) then
  310. if(TI_NPCDB[npcname]) then
  311. local thisnpc = TI_NPCDB[npcname];
  312. if(thisnpc.state) then
  313. for i,current in ipairs(thisnpc) do
  314. if(current.name == questname and current.state) then
  315. TI_CompleteQuest();
  316. end
  317. end
  318. else
  319. if(TI_IsNPCOn(UnitName("npc"), "activequest")) then
  320. TI_CompleteQuest();
  321. end
  322. end
  323. else
  324. if(TI_IsNPCOn(UnitName("npc"), "activequest")) then
  325. TI_CompleteQuest();
  326. end
  327. end
  328. end
  329. end
  330. function TI_CompleteQuest()
  331. if(IsQuestCompletable()) then
  332. TI_debug("quest is completable, completeing");
  333. CompleteQuest();
  334. TI_ResetPointers();
  335. else
  336. TI_debug("quest is not completable, declining");
  337. QuestDetailDeclineButton_OnClick();
  338. end
  339. end
  340. function TI_GetQuests(type)
  341. local numQuests = (getglobal("GetNum"..type.."Quests"))();
  342. local qfn = getglobal("Get"..type.."Title");
  343. local ret = {};
  344. local qname;
  345. local i=1;
  346. for i=1,numQuests do
  347. qname = qfn(i);
  348. ret[i] = {name=qname};
  349. end
  350. return ret;
  351. end
  352. function TI_HandleGossipWindow(gorq)
  353. local SAcQ;
  354. local SAvQ;
  355. local AvailableQuests;
  356. local ActiveQuests;
  357. local GossipOptions;
  358. if(gorq == "g") then
  359. AvailableQuests = TI_TabulateGossipQuestUIInfo(C_GossipInfo.GetAvailableQuests());
  360. ActiveQuests = TI_TabulateGossipQuestUIInfo(C_GossipInfo.GetActiveQuests());
  361. GossipOptions = TI_TabulateGossipUIInfo(C_GossipInfo.GetOptions());
  362. SAcQ = C_GossipInfo.SelectActiveQuest;
  363. SAvQ = C_GossipInfo.SelectAvailableQuest;
  364. elseif(gorq == "q") then
  365. AvailableQuests = TI_GetQuests("Available");
  366. ActiveQuests = TI_GetQuests("Active");
  367. GossipOptions = {};
  368. SAcQ=SelectActiveQuest;
  369. SAvQ=SelectAvailableQuest;
  370. end
  371. local ListEntry = {};
  372. for i,v in ipairs(AvailableQuests) do
  373. local x={};
  374. x.name = v.name;
  375. x.gorq = gorq;
  376. x.args = i;
  377. x.type = "availquest";
  378. x.icon = v.icon;
  379. x.state = false;
  380. table.insert(ListEntry, x);
  381. end
  382. for i,v in ipairs(ActiveQuests) do
  383. local x={};
  384. x.name = v.name;
  385. x.gorq = gorq;
  386. x.args = i;
  387. x.type = "activequest";
  388. x.icon = v.icon;
  389. x.state = false;
  390. table.insert(ListEntry, x);
  391. end
  392. for i,v in ipairs(GossipOptions) do
  393. local x={};
  394. x.name = v.name;
  395. x.gorq = gorq;
  396. x.args = i;
  397. x.type = v.type;
  398. x.state = false;
  399. table.insert(ListEntry, x);
  400. end
  401. ListEntry.state = false;
  402. local TotalOptions = #AvailableQuests+#ActiveQuests+#GossipOptions;
  403. --if(TI_activenumber > ActiveQuests.getn()) TI_activenumber = 1;
  404. if(TotalOptions < 1) then
  405. return;
  406. end
  407. local npcname = UnitName("npc");
  408. TI_AddNPCToTempList(npcname, ListEntry);
  409. if(TI_status.autoadd and (not TI_NPCDB[npcname])) then
  410. TI_debug("autoadd on, adding this NPC", TI_status.autoadd, TI_NPCDB[npcname]);
  411. TI_AddNPCToList(ListEntry, npcname);
  412. end
  413. -- If a NPC is in the Database but a new dialog option has appeared (new daily/completed quest) then add it to the DB
  414. if (TI_NPCDB[npcname]) then
  415. for k1, v1 in ipairs(ListEntry) do
  416. local found = false;
  417. for k2, v2 in ipairs(TI_NPCDB[npcname]) do
  418. if (v2.type == v1.type and v2.name == v1.name) then
  419. found = true;
  420. end
  421. end
  422. if (not found) then
  423. table.insert(TI_NPCDB[npcname], v1)
  424. TI_PopulateOptions("npclist updated");
  425. end
  426. end
  427. end
  428. if(TI_availnumber > TotalOptions or TI_activenumber > TotalOptions) then
  429. TI_ResetPointers();
  430. return;
  431. end
  432. TI_debug(npcname);
  433. if(TI_NPCDB[npcname]) then
  434. local thisnpc = TI_NPCDB[npcname];
  435. if(thisnpc.state) then
  436. TI_debug("npc is active, using his options");
  437. for i1,current in ipairs(thisnpc) do
  438. if (current.state == true) then
  439. TI_debug("Current Quest: "..current.name);
  440. if (TI_specnum == 0 or i1 > TI_specnum) then
  441. TI_specnum = i1;
  442. if (current.type == "availquest") then
  443. for i2,v2 in ipairs(AvailableQuests) do
  444. if (v2.name == current.name) then
  445. TI_debug(i1.."-Available Match Found: "..current.name);
  446. TI_FunctionList[current.gorq]["availquest"](i2);
  447. return;
  448. end
  449. end
  450. elseif (current.type == "activequest") then
  451. for i2,v2 in ipairs(ActiveQuests) do
  452. if (v2.name == current.name) then
  453. TI_debug(i1.."-Active Match Found: "..current.name..", "..current.type);
  454. TI_FunctionList[current.gorq]["activequest"](i2);
  455. return;
  456. end
  457. end
  458. else
  459. for i2,v2 in ipairs(GossipOptions) do
  460. if (v2.name == current.name) then
  461. TI_debug(i1.."-Gossip Match Found: "..current.name..", "..current.type);
  462. C_GossipInfo.SelectOption(i2);
  463. return;
  464. end
  465. end
  466. end
  467. end
  468. end
  469. end
  470. return;
  471. else
  472. TI_debug("npc in list, but not active");
  473. end
  474. else
  475. TI_debug("npc not in list");
  476. end
  477. if(TI_status.usedefault == false) then
  478. TI_debug("npc not in list, default set to off, returning.");
  479. return;
  480. end;
  481. TI_debug("using default config");
  482. for i,current in ipairs(TI_status.options) do
  483. if(current.state) then
  484. if(current.type == "availquest" and #AvailableQuests > 0 and TI_availnumber <= #AvailableQuests) then
  485. TI_availnumber = TI_availnumber + 1;
  486. SAvQ(TI_availnumber-1);
  487. TI_debug("Selecting Available Quest ".. TI_availnumber-1);
  488. TI_ResetPointers();
  489. return;
  490. elseif(current.type == "activequest" and #ActiveQuests > 0 and TI_activenumber <= #ActiveQuests) then
  491. while TI_activenumber <= #ActiveQuests do
  492. TI_activenumber = TI_activenumber + 1;
  493. if ActiveQuests[TI_activenumber-1].isComplete then
  494. TI_debug("Selecting Active Quest ".. TI_activenumber-1 .. " " .. ActiveQuests[TI_activenumber-1].name );
  495. SAcQ(TI_activenumber-1);
  496. TI_ResetPointers();
  497. return;
  498. else
  499. TI_debug("Active Quest ".. TI_activenumber-1 .. " " .. ActiveQuests[TI_activenumber-1].name .. " is not complete")
  500. end
  501. end
  502. elseif(#GossipOptions > 0) then
  503. for j,val in ipairs(GossipOptions) do
  504. if(val.type == current.type) then
  505. TI_ResetPointers();
  506. C_GossipInfo.SelectOption(j);
  507. return;
  508. end
  509. end
  510. end
  511. end
  512. end
  513. end
  514. function TI_AddNPCToList(OptList, npcname, confirminquestion)
  515. if (npcname == nil) then
  516. npcname = UnitName("npc");
  517. end
  518. if(#OptList > 0) then
  519. if(TI_NPCDB[npcname] == nil) then
  520. TI_NPCDB[npcname] = TI_copyTable(OptList);
  521. table.insert(TI_NPCIndex, npcname);
  522. table.sort(TI_NPCIndex);
  523. TI_PopulateOptions("npclist updated");
  524. elseif(confirminquestion == true) then
  525. TI_NPCDB[npcname] = TI_copyTable(OptList);
  526. TI_PopulateOptions("npclist updated");
  527. else
  528. TI_NPCInQuestion = {name=npcname, list=OptList};
  529. StaticPopup_Show("TI_NPCINQUESTION", npcname);
  530. end
  531. end
  532. end
  533. function TI_AddNPCToTempList(name, list)
  534. local temp = {};
  535. temp.name = name;
  536. temp.list = list;
  537. local subZone = GetSubZoneText();
  538. local realZone = GetRealZoneText();
  539. if(subZone == "") then
  540. temp.location = realZone;
  541. else
  542. temp.location = subZone .. ", " .. realZone;
  543. end
  544. table.insert(TI_TempNPCList, 1, temp);
  545. if(#TI_TempNPCList > TI_TempNPCListMaxSize) then
  546. table.remove(TI_TempNPCList, TI_TempNPCListMaxSize);
  547. end
  548. TI_TempNPCListUpdate();
  549. end
  550. function TI_DeleteTempNPCIndex(index)
  551. table.remove(TI_TempNPCList, index);
  552. TI_TempNPCListUpdate();
  553. end
  554. function TI_AddTempNPCIndex(index)
  555. TI_AddNPCToList(TI_TempNPCList[index].list, TI_TempNPCList[index].name);
  556. end
  557. function TI_DeleteNPC(index)
  558. local name = TI_NPCIndex[index];
  559. table.remove(TI_NPCIndex, index);
  560. TI_NPCDB[name] = nil;
  561. end
  562. function TI_StripDescriptors(...)
  563. local x = {};
  564. local arg = {...};
  565. for i=1, #arg, 2 do
  566. table.insert(x,arg[i]);
  567. end
  568. return x;
  569. end
  570. function TI_TabulateGossipOptions(...)
  571. local x = {};
  572. local arg = {...};
  573. for i=1, #arg, 2 do
  574. local temp = {};
  575. temp.name = arg[i];
  576. temp.type = arg[i+1];
  577. table.insert(x, temp);
  578. end
  579. return x;
  580. end
  581. function TI_TabulateGossipQuestUIInfo(gquis)
  582. local x = {};
  583. for i,gqui in ipairs(gquis) do
  584. local temp = {};
  585. temp.name = gqui.title;
  586. temp.icon = QuestUtil.GetQuestIconActive(gqui.isComplete, gqui.isLegendary,
  587. gqui.frequency, gqui.isRepeatable, gqui.isCampaign, gqui.isCovenantCalling);
  588. temp.isComplete = gqui.isComplete;
  589. table.insert(x, temp);
  590. end
  591. return x;
  592. end
  593. function TI_TabulateGossipUIInfo(guis)
  594. local x = {};
  595. for i,gui in ipairs(guis) do
  596. local temp = {};
  597. temp.name = gui.name;
  598. if gui.type == "chatbubble" then
  599. gui.type = "gossip"
  600. end
  601. temp.type = gui.type;
  602. table.insert(x, temp);
  603. end
  604. return x;
  605. end
  606. --[[this function stolen from WhisperCast by Sarris, whom I love dearly for his contribution to Paladins everywhere.
  607. ]]
  608. function TI_copyTable( src )
  609. local copy = {}
  610. for k1,v1 in pairs(src) do
  611. if ( type(v1) == "table" ) then
  612. copy[k1]=TI_copyTable(v1)
  613. else
  614. copy[k1]=v1
  615. end
  616. end
  617. return copy
  618. end
  619. function toggle(arg)
  620. if(arg) then
  621. return false;
  622. else
  623. return true;
  624. end
  625. end