Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  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 = SelectGossipAvailableQuest,
  35. activequest = SelectGossipActiveQuest,
  36. default = SelectGossipOption
  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. recent = function ()
  187. TI_TempNPCListWindow:Show();
  188. end,
  189. debug = function ()
  190. if(TI_status.debugstate) then
  191. TI_status.debugstate = false;
  192. TI_message("debug mode off");
  193. else
  194. TI_status.debugstate = true;
  195. TI_message("debug mode on");
  196. end
  197. end
  198. };
  199. if(commands[cmdlist[1]]) then
  200. commands[cmdlist[1]](cmdlist[2], cmdlist[3], cmdlist[4]);
  201. else
  202. 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");
  203. end
  204. end
  205. function TI_IsNPCOn(npcname, type)
  206. local opton = false;
  207. if(type ~= nil) then
  208. for k,v in pairs(TI_status.options) do
  209. if(v.type == type and v.state == true) then
  210. opton = true;
  211. end
  212. end
  213. else
  214. opton = true;
  215. end
  216. if(TI_NPCDB[npcname] == nil and TI_status.usedefault == true and opton == true) then
  217. TI_debug("case 1");
  218. return true;
  219. elseif(TI_NPCDB[npcname] ~= nil and TI_NPCDB[npcname].state) then
  220. TI_debug("case 2");
  221. return true;
  222. elseif(TI_NPCDB[npcname] ~= nil and TI_status.usedefault == true and not TI_NPCDB[npcname].state and opton == true) then
  223. TI_debug("case 4");
  224. return true;
  225. else
  226. TI_debug("case 3");
  227. return false;
  228. end
  229. end
  230. function TI_OnEvent(self, event, ...)
  231. if(event == "VARIABLES_LOADED") then
  232. TI_VarInit();
  233. if(TI_status.state) then
  234. TI_LoadEvents();
  235. end
  236. end
  237. if(TI_status.state and not IsShiftKeyDown()) then
  238. if(event == "QUEST_GREETING") then
  239. TI_debug("Quest Greeting");
  240. TI_lastquestframe = "greeting";
  241. if(QuestFrame:IsVisible()) then
  242. if(TI_gossipclosed) then
  243. TI_debug("resetting pointers");
  244. TI_gossipclosed = false;
  245. TI_ResetPointers();
  246. end
  247. TI_HandleGossipWindow("q");
  248. end
  249. end
  250. if(event == "GOSSIP_SHOW") then
  251. TI_debug("Gossip Show");
  252. if(GossipFrame:IsVisible()) then
  253. if(TI_gossipclosed) then
  254. TI_debug("resetting pointers");
  255. TI_gossipclosed = false;
  256. TI_ResetPointers();
  257. end
  258. TI_HandleGossipWindow("g");
  259. end
  260. end
  261. if(event == "GOSSIP_CLOSED") then
  262. TI_debug("Gossip Closed");
  263. if(not GossipFrame:IsVisible()) then
  264. TI_gossipclosed = true;
  265. end;
  266. end
  267. if(event == "QUEST_COMPLETE") then
  268. TI_debug("Quest Complete");
  269. if(TI_IsNPCOn(UnitName("npc"), "activequest")) then
  270. if(not (GetNumQuestChoices() > 1)) then
  271. GetQuestReward(1);
  272. end
  273. end
  274. TI_ResetPointers();
  275. end
  276. if(event == "QUEST_PROGRESS") then
  277. TI_debug("Quest Progress");
  278. TI_gossipclosed = false;
  279. TI_lastquestframe = "progress";
  280. TI_HandleQuestProgress();
  281. end
  282. if(event == "QUEST_DETAIL") then
  283. TI_debug("Quest Detail");
  284. TI_gossipclosed = false;
  285. if(TI_IsNPCOn(UnitName("npc"), "availquest")) then
  286. AcceptQuest();
  287. end
  288. TI_ResetPointers();
  289. end
  290. if(event == "QUEST_FINISHED") then
  291. TI_debug("Quest Finished");
  292. if(not QuestFrame:IsVisible() and TI_lastquestframe == "greeting") then
  293. TI_debug("looks like the quest frame closed, resetting pointers on next open");
  294. TI_gossipclosed = true;
  295. end
  296. end
  297. end
  298. end
  299. function TI_HandleQuestProgress()
  300. local questname = GetTitleText();
  301. local npcname = UnitName("npc");
  302. if(QuestFrame:IsVisible()) then
  303. if(TI_NPCDB[npcname]) then
  304. local thisnpc = TI_NPCDB[npcname];
  305. if(thisnpc.state) then
  306. for i,current in ipairs(thisnpc) do
  307. if(current.name == questname and current.state) then
  308. TI_CompleteQuest();
  309. end
  310. end
  311. else
  312. if(TI_IsNPCOn(UnitName("npc"), "activequest")) then
  313. TI_CompleteQuest();
  314. end
  315. end
  316. else
  317. if(TI_IsNPCOn(UnitName("npc"), "activequest")) then
  318. TI_CompleteQuest();
  319. end
  320. end
  321. end
  322. end
  323. function TI_CompleteQuest()
  324. if(IsQuestCompletable()) then
  325. CompleteQuest();
  326. TI_ResetPointers();
  327. else
  328. DeclineQuest();
  329. end
  330. end
  331. function TI_GetQuests(type)
  332. local numQuests = (getglobal("GetNum"..type.."Quests"))();
  333. local qfn = getglobal("Get"..type.."Title");
  334. local ret = {};
  335. local qname;
  336. local i=1;
  337. for i=1,numQuests do
  338. qname = qfn(i);
  339. ret[i] = {name=qname};
  340. end
  341. return ret;
  342. end
  343. function TI_HandleGossipWindow(gorq)
  344. local SAcQ;
  345. local SAvQ;
  346. local AvailableQuests;
  347. local ActiveQuests;
  348. local GossipOptions;
  349. if(gorq == "g") then
  350. AvailableQuests = TI_TabulateGossipAvailableQuests(GetGossipAvailableQuests());
  351. ActiveQuests = TI_TabulateGossipActiveQuests(GetGossipActiveQuests());
  352. GossipOptions = TI_TabulateGossipOptions(GetGossipOptions());
  353. SAcQ = SelectGossipActiveQuest;
  354. SAvQ = SelectGossipAvailableQuest;
  355. elseif(gorq == "q") then
  356. AvailableQuests = TI_GetQuests("Available");
  357. ActiveQuests = TI_GetQuests("Active");
  358. GossipOptions = {};
  359. SAcQ=SelectActiveQuest;
  360. SAvQ=SelectAvailableQuest;
  361. end
  362. local ListEntry = {};
  363. for i,v in ipairs(AvailableQuests) do
  364. local x={};
  365. x.name = v.name;
  366. x.gorq = gorq;
  367. x.args = i;
  368. x.type = "availquest";
  369. x.icon = v.icon;
  370. x.state = false;
  371. table.insert(ListEntry, x);
  372. end
  373. for i,v in ipairs(ActiveQuests) do
  374. local x={};
  375. x.name = v.name;
  376. x.gorq = gorq;
  377. x.args = i;
  378. x.type = "activequest";
  379. x.icon = v.icon;
  380. x.state = false;
  381. table.insert(ListEntry, x);
  382. end
  383. for i,v in ipairs(GossipOptions) do
  384. local x={};
  385. x.name = v.name;
  386. x.gorq = gorq;
  387. x.args = i;
  388. x.type = v.type;
  389. x.state = false;
  390. table.insert(ListEntry, x);
  391. end
  392. ListEntry.state = false;
  393. local TotalOptions = #AvailableQuests+#ActiveQuests+#GossipOptions;
  394. --if(TI_activenumber > ActiveQuests.getn()) TI_activenumber = 1;
  395. if(TotalOptions < 1) then
  396. return;
  397. end
  398. local npcname = UnitName("npc");
  399. TI_AddNPCToTempList(npcname, ListEntry);
  400. if(TI_status.autoadd and (not TI_NPCDB[npcname])) then
  401. TI_debug("autoadd on, adding this NPC", TI_status.autoadd, TI_NPCDB[npcname]);
  402. TI_AddNPCToList(ListEntry, npcname);
  403. end
  404. -- If a NPC is in the Database but a new dialog option has appeared (new daily/completed quest) then add it to the DB
  405. if (TI_NPCDB[npcname]) then
  406. for k1, v1 in ipairs(ListEntry) do
  407. local found = false;
  408. for k2, v2 in ipairs(TI_NPCDB[npcname]) do
  409. if (v2.type == v1.type and v2.name == v1.name) then
  410. found = true;
  411. end
  412. end
  413. if (not found) then
  414. table.insert(TI_NPCDB[npcname], v1)
  415. TI_PopulateOptions("npclist updated");
  416. end
  417. end
  418. end
  419. if(TI_availnumber > TotalOptions or TI_activenumber > TotalOptions) then
  420. TI_ResetPointers();
  421. return;
  422. end
  423. TI_debug(npcname);
  424. if(TI_NPCDB[npcname]) then
  425. local thisnpc = TI_NPCDB[npcname];
  426. if(thisnpc.state) then
  427. TI_debug("npc is active, using his options");
  428. for i1,current in ipairs(thisnpc) do
  429. if (current.state == true) then
  430. TI_debug("Current Quest: "..current.name);
  431. if (TI_specnum == 0 or i1 > TI_specnum) then
  432. TI_specnum = i1;
  433. if (current.type == "availquest") then
  434. for i2,v2 in ipairs(AvailableQuests) do
  435. if (v2.name == current.name) then
  436. TI_debug(i1.."-Available Match Found: "..current.name);
  437. TI_FunctionList[current.gorq]["availquest"](i2);
  438. return;
  439. end
  440. end
  441. elseif (current.type == "activequest") then
  442. for i2,v2 in ipairs(ActiveQuests) do
  443. if (v2.name == current.name) then
  444. TI_debug(i1.."-Active Match Found: "..current.name..", "..current.type);
  445. TI_FunctionList[current.gorq]["activequest"](i2);
  446. return;
  447. end
  448. end
  449. elseif (current.type == "gossip") then
  450. for i2,v2 in ipairs(GossipOptions) do
  451. if (v2.name == current.name) then
  452. SelectGossipOption(i2);
  453. return;
  454. end
  455. end
  456. end
  457. end
  458. end
  459. end
  460. return;
  461. else
  462. TI_debug("npc in list, but not active");
  463. end
  464. else
  465. TI_debug("npc not in list");
  466. end
  467. if(TI_status.usedefault == false) then
  468. TI_debug("npc not in list, default set to off, returning.");
  469. return;
  470. end;
  471. TI_debug("using default config");
  472. for i,current in ipairs(TI_status.options) do
  473. if(current.state) then
  474. if(current.type == "availquest" and #AvailableQuests > 0 and TI_availnumber <= #AvailableQuests) then
  475. TI_availnumber = TI_availnumber + 1;
  476. SAvQ(TI_availnumber-1);
  477. TI_debug("Selecting Available Quest ".. TI_availnumber-1);
  478. return;
  479. elseif(current.type == "activequest" and #ActiveQuests > 0 and TI_activenumber <= #ActiveQuests) then
  480. TI_activenumber = TI_activenumber + 1;
  481. SAcQ(TI_activenumber-1);
  482. TI_debug("Selecting Active Quest ".. TI_activenumber-1);
  483. return;
  484. elseif(#GossipOptions > 0) then
  485. for j,val in ipairs(GossipOptions) do
  486. if(val.type == current.type) then
  487. TI_ResetPointers();
  488. SelectGossipOption(j);
  489. return;
  490. end
  491. end
  492. end
  493. end
  494. end
  495. end
  496. function TI_AddNPCToList(OptList, npcname, confirminquestion)
  497. if (npcname == nil) then
  498. npcname = UnitName("npc");
  499. end
  500. if(#OptList > 0) then
  501. if(TI_NPCDB[npcname] == nil) then
  502. TI_NPCDB[npcname] = TI_copyTable(OptList);
  503. table.insert(TI_NPCIndex, npcname);
  504. table.sort(TI_NPCIndex);
  505. TI_PopulateOptions("npclist updated");
  506. elseif(confirminquestion == true) then
  507. TI_NPCDB[npcname] = TI_copyTable(OptList);
  508. TI_PopulateOptions("npclist updated");
  509. else
  510. TI_NPCInQuestion = {name=npcname, list=OptList};
  511. StaticPopup_Show("TI_NPCINQUESTION", npcname);
  512. end
  513. end
  514. end
  515. function TI_AddNPCToTempList(name, list)
  516. local temp = {};
  517. temp.name = name;
  518. temp.list = list;
  519. temp.location = GetSubZoneText() .. ", " .. GetRealZoneText();
  520. table.insert(TI_TempNPCList, 1, temp);
  521. if(#TI_TempNPCList > TI_TempNPCListMaxSize) then
  522. table.remove(TI_TempNPCList, TI_TempNPCListMaxSize);
  523. end
  524. TI_TempNPCListUpdate();
  525. end
  526. function TI_DeleteTempNPCIndex(index)
  527. table.remove(TI_TempNPCList, index);
  528. TI_TempNPCListUpdate();
  529. end
  530. function TI_AddTempNPCIndex(index)
  531. TI_AddNPCToList(TI_TempNPCList[index].list, TI_TempNPCList[index].name);
  532. end
  533. function TI_DeleteNPC(index)
  534. local name = TI_NPCIndex[index];
  535. table.remove(TI_NPCIndex, index);
  536. TI_NPCDB[name] = nil;
  537. end
  538. function TI_StripDescriptors(...)
  539. local x = {};
  540. local arg = {...};
  541. for i=1, #arg, 2 do
  542. table.insert(x,arg[i]);
  543. end
  544. return x;
  545. end
  546. function TI_TabulateGossipOptions(...)
  547. local x = {};
  548. local arg = {...};
  549. for i=1, #arg, 2 do
  550. local temp = {};
  551. temp.name = arg[i];
  552. temp.type = arg[i+1];
  553. table.insert(x, temp);
  554. end
  555. return x;
  556. end
  557. function TI_TabulateGossipAvailableQuests(...)
  558. local x = {};
  559. for i=1, select("#", ...), 5 do
  560. local temp = {};
  561. temp.name = select(i, ...);
  562. isTrivial = select(i+2, ...);
  563. isDaily = select(i+3, ...);
  564. isRepeatable = select(i+4, ...);
  565. if ( isDaily ) then
  566. temp.icon = "Interface\\GossipFrame\\DailyQuestIcon";
  567. elseif ( isRepeatable ) then
  568. temp.icon = "Interface\\GossipFrame\\DailyActiveQuestIcon";
  569. else
  570. temp.icon = "Interface\\GossipFrame\\AvailableQuestIcon";
  571. end
  572. table.insert(x, temp);
  573. end
  574. return x;
  575. end
  576. function TI_TabulateGossipActiveQuests(...)
  577. local x = {};
  578. for i=1, select("#", ...), 4 do
  579. local temp = {};
  580. temp.name = select(i, ...);
  581. isComplete = select(i+3, ...);
  582. if(isComplete) then
  583. temp.icon = "Interface\\GossipFrame\\ActiveQuestIcon";
  584. else
  585. temp.icon = "Interface\\GossipFrame\\IncompleteQuestIcon";
  586. end
  587. table.insert(x, temp);
  588. end
  589. return x;
  590. end
  591. --[[this function stolen from WhisperCast by Sarris, whom I love dearly for his contribution to Paladins everywhere.
  592. ]]
  593. function TI_copyTable( src )
  594. local copy = {}
  595. for k1,v1 in pairs(src) do
  596. if ( type(v1) == "table" ) then
  597. copy[k1]=TI_copyTable(v1)
  598. else
  599. copy[k1]=v1
  600. end
  601. end
  602. return copy
  603. end
  604. function toggle(arg)
  605. if(arg) then
  606. return false;
  607. else
  608. return true;
  609. end
  610. end