· 6 years ago · Nov 02, 2019, 06:24 AM
1<?xml version="1.0" encoding="iso-8859-1"?>
2<!DOCTYPE muclient>
3<muclient>
4<plugin
5 name="WinkleWinkle_Mapper_Extender_4_0"
6 author="WinkleWinkle"
7 id="b6eae87ccedd84f510b74715"
8 language="Lua"
9 purpose="Extends mapper functionality"
10 date_written="2017-12-10 16:37:14"
11 requires="4.76"
12 version="4.0"
13 save_state="y"
14 >
15
16<description trim="n">
17<![CDATA[
18
19MAPPER EXTENDER USAGE:
20
21===== SHOW THIS HELP =============>
22> extender help
23 - shows only this help
24> ww help
25 - all winklewinkle(tm) plugins show help
26
27===== RUNNING ====================>
28> xrunto [areaname]
29 - Runs you via mapper goto/walkto to the first room you discovered in that area
30
31> xrt [areaname]
32 - Same as "xrunto"
33
34> xset mark
35 - Sets the current room you are in to be the "first" room of that area
36
37> xset mark [roomnumber]
38 - Sets room [roomnumber] as the first room in the area that it belongs to
39
40> xset speed
41 - Toggles the use of mapper goto/walkto for all movement commands
42
43> xset speed <walk|run>
44 - changes the use of mapper goto/walkto for all movement commands
45
46> xmapper move <roomid>
47 - uses set movement speed to move to the specified room id
48
49> xmapper move <roomid> <walk|run>
50 - uses a temporary movement speed to move to the specified room id
51
52===== SEARCHING ==================>
53> xm [roomname]
54 - Lists and numbers rooms that match the [roomname] exactly, and then partial matches in the current area
55
56> xmall [roomname]
57 - Lists and numbers rooms that match the [roomname] exactly, and then partial matches in all areas
58
59===== ROOMS ======================>
60> go [index]
61 - Will run you with mapper goto/walkto to the first room in a numbered room list
62
63> go
64 - The same as typing "go 1"
65
66> nx
67 - Will run you to the next numbered room, "go" then "nx" would be the same as typing "go 1" then "go 2"
68
69===== CAMPAIGNS ==================>
70> xcp
71 - Lists all active campaign mobs in a numbered list (see xcp [index])
72
73> xcp [index]
74 - Area CP runs you to the area of that CP item and does a Quick-Where on your mob. Type "go [index]" after this to go to the first known room found (if any)
75 - Room CP lists all known rooms that exactly match your CP room name. Type "go [index]" to run to the right room (if any).
76
77===== NOTES ======================>
78> roomnote
79 - Lists all mapper notes for the current room (if any).
80
81> roomnote area
82 - Lists all mapper notes for the current area (if any). Useful for mazes
83
84===== SETTINGS ======================>
85> xset pk
86 - Toggles the display of PK flag in room searches
87
88> xset vidblain
89 - Toggles a hack that will allow you to speedwalk to vidblain areas if you do not have a portal to use
90
91> xset reset gui
92 - Will reset the X, Y and Z position of the Extender GUI
93
94== v3 ==
95===== GLOBAL QUESTS ==============>
96> qq
97 - refresh the global quest list (if you are on a global quest)
98 This will also refresh the GUI
99
100> qqreport <channel>
101 - will send a list of your incomplete GQ mobs to the channel of your choosing (eg qqreport gt)
102
103> xset gqrefresh
104 - Toggles the automatic refreshing of the GQ listing when a GQ mob is killed (for faster performance!)
105
106== v4 ==
107===== Performance Improv. & Unscramble Names ==============>
108> xname <index#>
109 - Execute while in area and it will search in-game mobdeath
110 Use xname gq <indedx#> for global QUESTS
111
112===== Bast Specific (requires Bast) ==============>
113> bna(ame) <mob name>
114 - Execute from anywhere and search personal Bast db
115
116> bast update
117 - Updates Bast database with unique mobs previously killed
118 Used for unscrambling names
119
120===== TO CREATE A CEXIT / MAP A PORTAL ==========>
121
122http://code.google.com/p/aardwolf-scriptalicious/wiki/MapperHelp
123
124]]>
125</description>
126
127</plugin>
128
129<!-- Timers -->
130
131<timers>
132
133 <timer
134 name="tim_init_plugin"
135 script="init_plugin"
136 enabled="y"
137 second="1">
138 </timer>
139
140 <timer
141 name="execute_in_area_timer"
142 script="execute_in_area_tick"
143 enabled="n"
144 second="0.25">
145 </timer>
146
147</timers>
148
149<!-- finding aliases -->
150
151<aliases>
152
153 <!-- debug -->
154
155 <alias
156 name="ali_toggle_debug"
157 match="^ext debug$"
158 regexp="y"
159 enabled="y"
160 sequence="100"
161 script="ext_debug"
162 >
163 </alias>
164
165 <alias match="^(?:ww|extender) help$"
166 enabled="y"
167 sequence="100"
168 send_to="12"
169 regexp="y"
170 keep_evaluating="y"
171 >
172 <send>
173 ColourNote("MediumSeaGreen", "", GetPluginInfo (GetPluginID (), 3))
174 </send>
175 </alias>
176
177 <!-- Settings -->
178
179 <alias
180 name="ali_set_pk"
181 match="^xset pk$"
182 regexp="y"
183 enabled="y"
184 sequence="100"
185 script="xset_pk"
186 >
187 </alias>
188
189 <alias match="^xset mark$"
190 enabled="y"
191 sequence="100"
192 script="xset_to_mark"
193 regexp="y"
194 >
195 </alias>
196
197 <alias match="^xset vidblain$"
198 enabled="y"
199 sequence="99"
200 script="set_check_vidblain"
201 regexp="y"
202 >
203 </alias>
204
205 <alias match="^xru?n?to? (.+)$"
206 enabled="y"
207 sequence="100"
208 script="xrun_to"
209 regexp="y"
210 >
211 </alias>
212
213 <alias
214 name="xm_request"
215 match="^xm(?:\ {(?<mob>[^\}]+)\})? (?<loc>.+)$"
216 enabled="y"
217 sequence="100"
218 script="map_area"
219 regexp="y"
220 >
221 </alias>
222
223 <alias match="^xmal?l?(?:\ {(?<mob>[^\}]+)\})? (?<loc>.+)$"
224 enabled="y"
225 sequence="99"
226 script="map_area_all"
227 regexp="y"
228 keep_evaluating="n"
229 >
230 </alias>
231
232
233 <alias match="^(?<cmd>cp|ca|cam|camp|campa|campai|campaig|campaign) (?<param>c|ch|che|check)$"
234 enabled="y"
235 sequence="5"
236 script="campaign_check"
237 regexp="y"
238 >
239 </alias>
240 <alias match="^(?<cmd>xcp) ?(?<param>c|ch|che|chec|check|test)?$"
241 enabled="y"
242 sequence="6"
243 script="campaign_check"
244 regexp="y"
245 >
246 </alias>
247
248 <alias match="^got?o?( (?<id>.+))?$"
249 enabled="y"
250 sequence="100"
251 script="goto_number"
252 regexp="y"
253 >
254 </alias>
255
256 <alias match="^nx$"
257 enabled="y"
258 sequence="100"
259 script="goto_next"
260 regexp="y"
261 >
262 </alias>
263
264 <alias match="^(xcp|cp|ca|cam|camp|campa|campaign) (?<index>[0-9]+)$"
265 enabled="y"
266 sequence="100"
267 script="goto_cp"
268 regexp="y"
269 >
270 </alias>
271 <!-- speed -->
272
273 <alias match="^xset speed ?(?<speed>run|walk)?$"
274 enabled="y"
275 sequence="100"
276 script="set_speed"
277 regexp="y"
278 >
279 </alias>
280
281 <alias match="^xma?p?p?e?r? move (?<roomid>[0-9]+|light|nomap_Camp Room_light) ?(?<speed>run|walk)?$"
282 enabled="y"
283 sequence="95"
284 ignore_case="y"
285 script="move_trigger"
286 regexp="y"
287 >
288 </alias>
289
290 <!-- roomnotes -->
291
292 <alias match="^r(?:oomnote|n)$"
293 enabled="y"
294 sequence="100"
295 script="room_note"
296 regexp="y"
297 >
298 </alias>
299
300 <alias match="^r(?:oomnote|n) a(?:rea)?(?: (?<areaid>.+))?$"
301 enabled="y"
302 sequence="99"
303 script="room_note_area"
304 regexp="y"
305 >
306 </alias>
307
308 <alias match="^xmapper purge room$"
309 enabled="y"
310 sequence="100"
311 script="map_purgeroom"
312 regexp="y"
313 >
314 </alias>
315
316 <!-- Sql Execution -->
317
318 <alias name="runsql"
319 match="^runsql (?<sql>.+)$"
320 enabled="y"
321 sequence="1"
322 script="RunSql"
323 regexp="y"
324 >
325 </alias>
326
327 <alias name="execsql"
328 match="^execsql (?<sql>.+)$"
329 enabled="y"
330 sequence="1"
331 script="ExecSql"
332 regexp="y"
333 >
334 </alias>
335 <alias name="ali_simulate_list"
336 match="^qq(?<debug>test)$"
337 enabled="y"
338 sequence="1"
339 script="gq_list_simulate"
340 regexp="y"
341 >
342 </alias>
343
344 <!-- GQ -->
345 <!-- v3 -->
346 <alias match="^qqrep(?:ort)? (?<channel>.+)$"
347 enabled="y"
348 sequence="100"
349 script="qq_report"
350 regexp="y"
351 >
352 </alias>
353
354 <alias match="^xset gqrefresh$"
355 enabled="y"
356 sequence="100"
357 script="set_gq_refresh"
358 regexp="y"
359 >
360 </alias>
361
362 <alias name="ali_gq_list"
363 match="^qq$"
364 enabled="y"
365 sequence="2"
366 script="gq_list"
367 regexp="y"
368 >
369 </alias>
370
371 <alias name="ali_goto_gq"
372 match="^qq (?<index>[0-9]+)$"
373 enabled="y"
374 sequence="2"
375 script="goto_gq"
376 regexp="y"
377 >
378 </alias>
379
380</aliases>
381
382<triggers>
383 <trigger
384 name="trg_cp_request"
385 match="^Commander Barcett tells you \'Good luck in your campaign\!\'$"
386 enabled="y"
387 regexp="y"
388 sequence="100"
389 script="campaign_check"
390 >
391 </trigger>
392
393 <trigger
394 name="trg_cp_mob_dead"
395 match="Congratulations, that was one of your CAMPAIGN mobs!"
396 enabled="y"
397 sequence="100"
398 script="campaign_check"
399 >
400 </trigger>
401
402 <trigger match="^You still have to kill \* (?<mob>[^\(]+) \((?<where>.+?)(?<isdead> - Dead)?\)\.?$"
403 name="trg_xcp_line"
404 script="capture_index_line"
405 enabled="n"
406 regexp="y"
407 omit_from_output="y"
408 sequence="500">
409 </trigger>
410
411 <trigger match="^(?!You still have to kill \*)"
412 name="trg_xcp_line_end"
413 script="xcp_index_line_end"
414 enabled="n"
415 regexp="y"
416 omit_from_output="y"
417 sequence="500">
418 </trigger>
419
420 <trigger match="You are not currently on a campaign."
421 name="trg_xcp_line_end_none"
422 script="xcp_index_line_end"
423 enabled="y"
424 regexp="n"
425 omit_from_output="n"
426 sequence="500">
427 </trigger>
428
429 <!-- area grabber -->
430 <trigger match=" [ Listing all areas in range * to * ]"
431 name="trg_area_index_start_gag"
432 script="area_index_start_gag"
433 enabled="y"
434 regexp="n"
435 omit_from_output="n"
436 sequence="100">
437 </trigger>
438
439 <trigger match="^From To Lock Builder Area Name"
440 name="trg_area_index_start"
441 script="area_index_start"
442 enabled="n"
443 regexp="y"
444 omit_from_output="n"
445 sequence="100">
446 </trigger>
447
448 <trigger match="---- ---- ---- --------------- ------------------------------"
449 name="trg_area_index_gag1"
450 enabled="n"
451 regexp="n"
452 omit_from_output="n"
453 sequence="100">
454 </trigger>
455 <trigger match="---------------------------------------------------------------"
456 name="trg_area_index_gag2"
457 enabled="n"
458 regexp="n"
459 omit_from_output="n"
460 sequence="100">
461 </trigger>
462
463 <trigger match="^ (?<min>[0-9 ]{3}) (?<max>[0-9 ]{3}) (?<lock>[0-9 ]{3}) (?<author>.{15}) (?<area>.+)$"
464 name="trg_area_index_line"
465 script="area_index_line"
466 enabled="n"
467 regexp="y"
468 omit_from_output="n"
469 sequence="100">
470 </trigger>
471
472 <trigger match="'Lock' means you cannot enter until you are that level or higher."
473 name="trg_area_index_end"
474 script="area_index_end"
475 enabled="n"
476 regexp="n"
477 omit_from_output="n"
478 sequence="100">
479 </trigger>
480
481
482 <!-- gq helper -->
483 <!-- v3 -->
484 <trigger match="^You still have to kill (?<qty>[0-9]) \* (?<mob>[^\(]+) \((?<where>.+?)(?<isdead> - Dead)?\)$"
485 name="x_gq_line"
486 group="x_gq"
487 enabled="n"
488 regexp="y"
489 omit_from_output="y"
490 sequence="500"
491 script="capture_index_line"
492 >
493 </trigger>
494
495 <trigger match="^(?!You still have to kill )"
496 name="x_gq_line_end"
497 group="x_gq"
498 enabled="n"
499 regexp="y"
500 omit_from_output="y"
501 sequence="500"
502 script="capture_gq_line_end"
503 >
504 </trigger>
505
506 <trigger match="You are not in a global quest."
507 name="x_gq_line_end_none"
508 enabled="y"
509 regexp="n"
510 omit_from_output="n"
511 sequence="500"
512 script="capture_gq_line_finished"
513 >
514 </trigger>
515
516 <trigger match="^You are no longer part of Global Quest # (?:\d+) and will be unable to rejoin.$"
517 name="x_gq_line_end_none2"
518 enabled="y"
519 regexp="y"
520 omit_from_output="n"
521 sequence="500"
522 script ="capture_gq_line_finished"
523 >
524 </trigger>
525 <trigger
526 match="You were the first to complete this quest!"
527 name="x_gq_line_end_none4"
528 enabled="y"
529 regexp="n"
530 omit_from_output="n"
531 sequence="500"
532 script ="capture_gq_line_finished"
533 >
534 </trigger>
535
536 <trigger
537 match="You have already completed this global quest."
538 name="x_gq_line_end_none3"
539 enabled="y"
540 regexp="n"
541 omit_from_output="n"
542 sequence="500"
543 script ="capture_gq_line_finished"
544 >
545 </trigger>
546
547 <trigger match="You have finished this global quest."
548 name="x_gq_line_end_none5"
549 enabled="y"
550 regexp="n"
551 omit_from_output="n"
552 sequence="500"
553 script="capture_gq_line_finished"
554 >
555 </trigger>
556
557 <trigger
558 enabled="y"
559 group="GlobalQuest"
560 match="^Global Quest\: The global quest for levels .+ to .+ has now started\.$"
561 regexp="y"
562 script="gq_list"
563 sequence="100"
564 >
565 </trigger>
566
567 <trigger
568 name="trigger_gq_mob_dead"
569 enabled="n"
570 group="GlobalQuest"
571 match="Congratulations, that was one of the GLOBAL QUEST mobs!"
572 script="gq_refresh"
573 sequence="100"
574 >
575 </trigger>
576
577
578 ---v4 adding highlight to mobs
579 <trigger
580 enabled="y"
581 match="{scan}"
582 script="togglescan"
583 omit_from_output="y"
584 name="scanon"
585 sequence="100"
586 group="scantag"
587 />
588 <trigger
589 enabled="y"
590 match="{/scan}"
591 script="togglescan"
592 omit_from_output="y"
593 name="scanoff"
594 sequence="100"
595 group="scantag"
596 />
597 <trigger
598 enabled="n"
599 script="checkmob"
600 match="^ \- (\(.*\))* *(.+)$"
601 name="checkmob"
602 omit_from_output="y"
603 regexp="y"
604 sequence="100"
605 group="scan"
606 />
607
608--- v4 adding missing triggers
609
610<trigger
611 match="You are not currently on a campaign."
612 script="xcp_index_line_end"
613 name="xcp_not_on_cp"
614 enabled="y"
615 regexp="n"
616 omit_from_output="n"
617 sequence="100"
618 >
619</trigger>
620<trigger
621 match="You will have to level before you can go on another campaign."
622 script="xcp_index_line_end"
623 name="xcp_wait_on_cp"
624 enabled="n"
625 regexp="n"
626 omit_from_output="n"
627 sequence="100"
628 >
629</trigger>
630</triggers>
631<variables>
632 <variable name="example"></variable>
633</variables>
634
635<!-- Get our standard constants -->
636<include name="constants.lua"/>
637
638<!-- Script -->
639<script>
640
641
642<![CDATA[
643
644 require "serialize"
645 require "gmcphelper"
646 require "tprint"
647
648 -- Variables --
649 local showDebug = 0
650
651 local search_destroy_id = "e50b1d08a0cfc0ee9c442001"
652 local mob_mapper_id = "b555825a4a5700c35fa80800"
653
654 local searchResult = {}
655 local searchIndex = 0
656 local cpList = {}
657 local listIndex = 1
658
659 local mode = nil
660 local gotoList = {}
661 local gotoIndex = 1
662 local currentRoom = ""
663
664 local char_status
665
666 local next_room = -1
667 local last_area = ""
668
669
670
671 local mapper_area_index = 0
672
673 local last_substitute
674
675 local speed = "run"
676
677
678 local showPK = GetVariable("showPK") or "true"
679 local USER_check_vidblain = GetVariable("XRunToCheckVidblain") or "false"
680 local USER_show_help = "true"
681 --local USER_run_if_one_room = true
682
683 local init_called = 0
684
685 local area_range = {}
686
687 local area_range = {}
688
689 local areaStartRooms = {}
690 if (GetVariable("areaStartRooms") ~= nil) then
691 luastmt = "obj = " .. GetVariable("areaStartRooms")
692 assert (loadstring (luastmt or "")) ()
693 areaStartRooms = obj
694 end
695
696
697 -------- GQ -------
698 -- v3 --
699
700 local gqList = {}
701 local gqIndex = 1
702 local USER_gq_mob_dead_refresh = GetVariable("GQMobDeadRefresh") or "false"
703 ---------------------
704
705 -------- V4 -------
706 local cpList_old = {}
707 local gqList_old = {}
708 local old_list = {}
709 local xname_mobs = {}
710 local name_mode = ""
711 local has_bast = 1
712
713 function init_plugin()
714
715 if (init_called < 2) then
716
717 Execute("sendgmcp request char")
718
719 local localchar = char_status
720 if (localchar ~= nil and tonumber(localchar.state) == 3) then
721
722 if (init_called == 0) then
723 Execute("xset suspend page size")
724 init_called = 1
725 else
726
727 EnableTimer("tim_init_plugin", false)
728 init_called = 2
729
730 Execute("sendgmcp request room")
731
732 -- trigger a search for area limits
733 SendNoEcho("area 0 298")
734
735 init_triggers()
736
737 end
738
739 end
740 end
741
742
743
744 end
745
746
747 -- v3 --
748 function init_triggers()
749
750 DebugNote("init - " ..USER_gq_mob_dead_refresh)
751 if (USER_gq_mob_dead_refresh == "true") then
752 EnableTrigger("trigger_gq_mob_dead", true)
753 else
754 EnableTrigger("trigger_gq_mob_dead", false)
755 end
756
757 -- v3 --
758 local msg = string.format("GQ Mob Dead Refresh : %s", tostring(GetTriggerInfo("trigger_gq_mob_dead", 8)))
759 DebugNote(msg)
760 end
761
762 local questMob = ""
763 local onQuest = false
764 function OnPluginBroadcast (msg, id, name, text)
765
766 -- Look for GMCP handler.
767 if (id == '3e7dedbe37e44942dd46d264') then
768 if (text == "room.info") then
769 res, gmcparg = CallPlugin("3e7dedbe37e44942dd46d264","gmcpval","room.info")
770
771 luastmt = "gmcpdata = " .. gmcparg
772 assert (loadstring (luastmt or "")) ()
773
774 currentRoom = {
775 roomid = gmcpval("num"),
776 areaid = gmcpval("zone")
777 }
778 elseif (text == "char.status") then
779 res, gmcparg = CallPlugin("3e7dedbe37e44942dd46d264","gmcpval","char.status")
780 luastmt = "gmcpdatacharstatus = " .. gmcparg
781 assert (loadstring (luastmt or "")) ()
782 char_status = gmcpdatacharstatus
783 --tprint(char_status)
784
785 --currentState = tonumber(gmcpval("status.state"))
786
787 ---v4 adding highlight to mobs
788 elseif text == ("comm.quest") then
789 res, gmcparg = CallPlugin("3e7dedbe37e44942dd46d264","gmcpval","comm.quest")
790 stuff = assert (loadstring ('return ' .. gmcparg or ""))()
791
792 if stuff.action == "ready" then
793 -- did not work first time
794 --Note("ready")
795 elseif stuff.action == "start" then
796 -- worked first time
797 --Note("start")
798 onQuest = true
799 questMob = stuff.targ
800 --Note("got a mob: " .. tostring(questMob))
801 elseif stuff.action == "killed" then
802 -- worked for me the first time
803 --Note("action kill ")
804 onQuest = false
805 questMob = ""
806 --Note("Quest mob killed, s/b blank : " .. tostring(questMob))
807 elseif stuff.action == "comp" then
808 -- worked for me first time
809 --Note("completed")
810 onQuest = false
811 end
812
813 if stuff.action == "fail" or stuff.action == "timeout" then
814 Note("fail or timeout")
815 onQuest = false
816 questMob = ""
817 Note("Quest mob fail/timeout, s/b blank : " .. tostring(questMob))
818 end
819
820 if stuff.target == "killed" then
821 Note("target kill ")
822 onQuest = false
823 questMob = ""
824 Note("Quest mob killed v2, s/b blank : " .. tostring(questMob))
825 end
826 end
827 end
828
829 end
830
831 function set_speed(name, line, wildcards)
832 if (wildcards.speed ~= "") then
833 speed = wildcards.speed
834 else
835 if (speed == "walk") then
836 speed = "run"
837 else
838 speed = "walk"
839 end
840 end
841 ColourNote("darkorange", "", "Move speed:" .. speed)
842 end
843
844
845 function move_trigger(name, line, wildcards)
846
847 if (wildcards.roomid ~= "") then
848
849 move(wildcards.roomid, wildcards.speed)
850 end
851
852
853 end
854
855 function move(roomid, temp_speed)
856 if (temp_speed == nil or temp_speed == "") then
857 temp_speed = speed
858 end
859 if (temp_speed == "walk") then
860 Note("walking to " .. roomid)
861 Execute("mapper walkto " .. roomid)
862 else
863 Execute("mapper goto " .. roomid)
864 end
865 end
866
867 local last_cp_check = os.time()
868 local xcp_flag = false
869
870--- V4
871function campaign_check(name, line, args)
872
873 --Note("campaign list old check is " .. #cpList_old)
874 --Note("campaign cpList has " .. #cpList)
875 if has_bast and name == "trg_cp_mob_dead" then
876 -- no need b/c bast already sends a cp check
877 return
878 end
879 DebugNote("campaign_check " .. tostring(name))
880
881 xcp_flag = true
882
883 -- prevent double cp checks from different plugins
884 local time_check = os.time()
885 if ((time_check - last_cp_check) < 2) and name ~= "trg_cp_mob_dead" then
886 ColourNote("darkorange","", "Winkle Extender: Slow down, can only send cp check every 2 seconds")
887 return
888 end
889
890 last_cp_check = time_check
891
892 cpList_old = cpList
893 cpList = {}
894 onCp = true
895
896 EnableTrigger("trg_xcp_line", true)
897 EnableTrigger("trg_xcp_line_end", false)
898
899 if (args.param == "test") then
900 cp_simulate()
901 elseif has_bast == false then
902 Send("cp check")
903 else
904 -- bast's broadcast_cp.xml will take care of sending cp checks
905 -- use zhalut's modifies copy of broadcast_cp.xml
906 if name == "trg_cp_mob_dead" then
907 -- should not reach here. taken care of at the top of the function
908 Note("campaign_check: campaign mob")
909 else
910 --Note("campaign_check: here")
911 -- not sending because Bast's cp tracker script sends cp check
912 --Send("cp check")
913 end
914 end
915end
916
917
918function capture_index_line(name, line, args)
919 -- for both GQ and CP
920 DebugNote("check_exist")
921 local mobQty = 1
922 if name == "trg_xcp_line" then
923 EnableTrigger("trg_xcp_line_end", true)
924 --if cpList == nil then cpList = {} end
925 --if cpList_old == nil then cpList_old = {} end
926 old_list = cpList_old
927 list = cpList
928 elseif name == "x_gq_line" then -- gq
929 EnableTrigger("x_gq_line_end", true)
930 mobQty = tostring(args.qty)
931 old_list = gqList_old
932 list = gqList
933 else
934 ColourNote("darkorange","", "Unknown source in index_line")
935 return
936 end
937 local skip = false
938 if #list == 0 or #old_list == 0 then skip = true end -- go right to sql to gather data
939
940 local fnd = false
941
942 if not skip then -- increment if exists
943 for i, v in ipairs(list) do
944 if args.mob == v.origMob and args.where == v.where then
945 list[i].qty = list[i].qty + mobQty
946 fnd = true
947 end
948 end
949 end
950
951
952 if not fnd then -- look for it in old list
953 for i , v in ipairs (old_list) do
954 --if not fnd then
955 if v.origMob == args.mob and v.where == args.where then
956 copy_mob(list, args.mob, i, mobQty, args.where, args.isdead,old_list)
957 --or else it could duplicate records
958 fnd = true
959 end
960 --end
961 end
962 end
963
964 --function get_rooms_areas(list, place, mobName, qty, isDead, listType)
965 if not fnd then -- doesn't exist, get run query to get info
966-- Note("get " .. args.mob)
967 if name == "trg_xcp_line" then
968 get_rooms_areas(list, args.where, args.mob, mobQty, args.isdead,"cp")
969 elseif name == "x_gq_line" then
970 get_rooms_areas(list, args.where, args.mob, mobQty, args.isdead,"gq")
971 end
972 end
973end
974
975function copy_mob(cpList, mob, old_index, qty, place, isDead, old_list)
976
977 --DebugNote("copy_mob " .. tostring(mob) .. " " .. tostring(old_index) .. " " .. tostring(qty) .. " " .. tostring(isDead))
978 -- copy from old to new
979 local listIndex = #list + 1
980 list[listIndex] = {
981 qty = qty,
982 mob = old_list[old_index].mob,
983 origMob = old_list[old_index].origMob,
984 distance = old_list[old_index].distance,
985 type = old_list[old_index].type,
986 roomId = old_list[old_index].roomId,
987 roomName = old_list[old_index].roomName,
988 landingRoom = old_list[old_index].landingRoom,
989 areaId = old_list[old_index].areaId,
990 sortId = old_list[old_index].sortId,
991 areaName = old_list[old_index].areaName,
992 area = old_list[old_index].area,
993 isDead = isDead,
994 min = old_list[old_index].min,
995 max = old_list[old_index].max,
996 info = old_list[old_index].info,
997 bast_kills = old_list[old_index].bast_kills,
998 where = old_list[old_index].where,
999 is_multi_area = old_list[old_index].is_multi_area,
1000 is_clean = old_list[old_index].is_clean
1001 }
1002
1003 --Note("copied " .. list[listIndex].mob .. " " .. list[listIndex].qty .. " " .. list[listIndex].type)
1004end
1005
1006------- V4 END -------
1007 local get_rooms_areas_sql =
1008 " SELECT r.uid as room, r.name as roomName, a.uid as area, a.name as areaName, 'room' as type, info " ..
1009 " FROM rooms r " ..
1010 " INNER JOIN areas a ON r.area = a.uid " ..
1011 " WHERE r.name = %s " ..
1012 " UNION " ..
1013 " SELECT -1 as room, '' as roomName, uid as area, name as areaName, 'area' as type, '' as info " ..
1014 " FROM areas " ..
1015 " WHERE name = %s " ..
1016 " ORDER BY type ASC "
1017-- get_rooms_areas(cpList, args.where, args.mob, 1, args.isdead)
1018
1019 function get_rooms_areas(list, place, mobName, qty, isDead, listType)
1020 local localLevel = -1
1021 if (char_status == nill) then
1022 DebugNote("Unknown char status")
1023 return
1024 else
1025 localLevel = tonumber(char_status.level)
1026 end
1027
1028 -- update quantity in table
1029 local skip = false
1030 for i, mob in ipairs(list) do
1031 if mobName == mob.origMob and place == mob.where then
1032 list[i].qty = list[i].qty + tonumber(qty)
1033 Note("get rooms: update qty" .. mobName .. "x " .. list[i].qty .. " " .. list[i].type )
1034 skip = true
1035 end
1036 end
1037
1038 if skip then
1039 return
1040 end
1041
1042 local listIndex = 0
1043 if listType == "cp" then
1044 listIndex = #cpList + 1
1045 elseif listType == "gq" then
1046 listIndex = #gqList + 1
1047 end
1048
1049 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1050 local db = assert(sqlite3.open(worldPath .. ".db"))
1051
1052 -- room/area
1053 local select = string.format (get_rooms_areas_sql, fixsql(place), fixsql(place))
1054 --DebugNote(select)
1055
1056 local index = 0
1057 local lastMobSignature = ""
1058
1059 local cnt = 0
1060
1061 for row in db:nrows(select) do
1062 local tolerance = 11
1063 local area_tolerance = 50
1064 local min = (area_range[row.areaName] or {min = 0}).min
1065 local max = (area_range[row.areaName] or {max = 300}).max
1066 -- debug
1067 --min = 0
1068 --max = 300
1069
1070 if (row.type == "room") then
1071 --Note("room")
1072
1073 -- filter out spammy neighbouring rooms.. too much spam!
1074 local mobSignature = row.areaName .. "|" .. mobName
1075
1076 --DebugNote("lastMobSignature:" .. lastMobSignature .. ":mobSignature:" .. mobSignature)
1077
1078 -- sanitize text room ids for "unmappable" rooms that are now being mapped
1079 row.room = (tonumber(row.room) or "nomap")
1080
1081 if (lastMobSignature ~= mobSignature) then
1082 if (localLevel >= (min - tolerance) and localLevel <= (max + tolerance)) then
1083 --Note(mobName .. " | " .. " Room cnt: " .. tostring(cnt))
1084 --Note(mobName .. " | " .. tostring(mob_guess) .. " guess: " .. tostring(dist))
1085 local is_multi_area = 0
1086 cnt = cnt + 1
1087 if cnt > 1 then is_multi_area = 1 end
1088
1089 local sortId = row.area
1090
1091 --ColourNote("lime","","get rooms " .. place .. " " .. mobName .. " " .. row.area .. " " .. bast_kills)
1092
1093 index = index + 1
1094
1095 list[listIndex] = {
1096 qty = tonumber(qty),
1097 mob = mobName,
1098 origMob = mobName,
1099 distance = 0,
1100 type = row.type,
1101 roomId = row.room,
1102 roomName = row.roomName,
1103 landingRoom = -1,
1104 areaId = row.area,
1105 sortId = row.area,
1106 areaName = row.areaName,
1107 area = row.area,
1108 isDead = isDead,
1109 min = min,
1110 max = max,
1111 info = row.info,
1112 bast_kills = 0,
1113 where = place,
1114 is_multi_area = 0,
1115 is_clean = false}
1116
1117 listIndex = listIndex + 1
1118 else
1119 local link = string.format("Ignoring due to level : %s in '%s' (%s) [%s-%s]", mobName, row.roomName, row.area, min, max)
1120 Hyperlink("xm move " .. row.room, link, "Move to room " .. row.room, "Khaki", "black", 0)
1121 print("")
1122 end
1123 end
1124
1125 lastMobSignature = mobSignature
1126
1127 else -- area
1128 --Note("area")
1129 --if (localLevel >= (min - area_tolerance) and localLevel <= (max + area_tolerance)) then
1130 --Note(mobName .. " | " .. " Area cnt: " .. tostring(cnt))
1131 --Note(mobName .. " | " .. tostring(mob_guess) .. " guess: " .. tostring(dist))
1132
1133 local is_multi_area = 0
1134 cnt = cnt + 1
1135 if cnt > 1 then is_multi_area = 1 end
1136
1137 index = index + 1
1138
1139 --DebugNote("get_rooms_areas - area:" .. index .. ":" .. mobName)
1140 --listIndex = #cpList + 1
1141 -- Note("list: " .. listType)
1142 list[listIndex] = {
1143 qty = tonumber(qty),
1144 mob = mobName,
1145 origMob = mobName,
1146 distance = 0,
1147 type = row.type,
1148 roomId = row.room,
1149 roomName = row.roomName,
1150 landingRoom = -1,
1151 areaId = row.area,
1152 sortId = row.area,
1153 areaName = row.areaName,
1154 area = row.area,
1155 isDead = isDead,
1156 bast_kills = 0,
1157 where = place,
1158 is_multi_area = 0,
1159 is_clean = false}
1160
1161 listIndex = listIndex + 1
1162 --end
1163 end
1164
1165 end
1166 db:close_vm()
1167
1168 DebugNote(mobName .. " index:" .. index)
1169 -- add unknown mobs
1170 if (index == 0) then
1171 listIndex = #list + 1
1172
1173 list[listIndex] = {
1174 qty = tonumber(qty),
1175 mob = mobName,
1176 origMob = mobName,
1177 distance = 0,
1178 type = "unknown",
1179 roomId = 0,
1180 roomName = place,
1181 landingRoom = -1,
1182 areaId = "UNKNOWN",
1183 sortId = "UNKNOWN",
1184 areaName = "UNKNOWN",
1185 area = "UNKNOWN",
1186 isDead = isDead,
1187 bast_kills = 0,
1188 where = place,
1189 is_multi_area = 0,
1190 is_clean = false}
1191
1192 end
1193 end
1194 function clean_list(list)
1195 if #list == 0 then
1196 return
1197 end
1198 --------- BEGIN: remove dupes ---------
1199 for i, v in ipairs (list) do
1200 if not v.is_clean and v.type == "area" then -- favor areas over rooms
1201 for k, m in ipairs(list) do
1202 if m.origMob == v.origMob and m.type == "room" and m.areaId == v.areaId then
1203 table.remove(list,k)
1204 end
1205 end
1206 end
1207 end
1208
1209 --------- END: remove dupes ---------
1210
1211
1212 if has_bast == 1 then
1213 db_bast = assert(sqlite3.open(GetInfo(66).."\\logs\\stats.db"))
1214 end
1215
1216 --------- BEGIN: add mobcount ---------
1217
1218 local mob_count = 0
1219 if has_bast == 1 then
1220 local sql_bast = ""
1221 --db_bast = assert(sqlite3.open(GetInfo(66).."\\logs\\stats.db"))
1222 for i, v in ipairs (list) do
1223 if not v.is_clean then
1224
1225 --sql_bast = [[where mk.name like '%]] .. v.origMob .. [[%']]
1226 --sql_bast = [[where mk.name like "%]] .. v.mob .. [[%"]]
1227 --sql_bast = [[where mk.name like '%]] .. (string.gsub (v.origMob, "'", "''")) .. [[%']]
1228 sql_bast = [[where mk.name = ]] .. fixsql(v.origMob)
1229 sql_bast = sql_bast .. " and " .. [[mk.area = "]] .. v.areaId .. [["]]
1230 if type == "room" then
1231 sql_bast = sql_bast .. " and " .. [[mk.room_id = "]] .. v.where .. [["]]
1232 end
1233
1234 sql_bast = [[select count(*) as kills, count(distinct mk.room_id) as rooms, max(mk.room_id) as max_rm_id
1235 from mobkills mk]] .. "\n" ..
1236 sql_bast
1237
1238 --Note(sql_bast)
1239 -- update mob killed count
1240 for row in db_bast:nrows(sql_bast) do
1241 v.bast_kills = row.kills
1242 if row.rooms == 1 then
1243 v.known_room = row.max_rm_id
1244 end
1245 --Note(row.kills .. " " .. tostring(row.rooms) .. " " .. tostring(row.max_rm_id))
1246 end
1247 end -- clean check
1248 end -- end for
1249 --db_bast:close()
1250
1251
1252 end
1253
1254 --------- END: add mobcount ---------
1255
1256 --------- BEGIN: group duplicate areas and sort ---------
1257
1258 for i, v in ipairs (list) do
1259 local cnt = 0
1260 for k, m in ipairs(list) do
1261 if v.origMob == m.origMob and v.where == m.where then
1262 cnt = cnt + 1
1263 if v.bast_kills > m.bast_kills then
1264 m.sortId = v.areaId
1265 else
1266 v.sortId = m.sortId
1267 end
1268 end
1269 end
1270 if cnt > 1 then
1271 v.is_multi_area = 1
1272 end
1273 v.is_clean = true
1274 end
1275
1276 -- sort
1277
1278 --[[ show current list
1279 for i,v in ipairs(list) do
1280
1281 Note(v.origMob .. " " .. v.qty .. " " .. v.areaId .. " " .. v.sortId .. " " .. v.bast_kills .. " " .. v.type .. ": " .. i)
1282 end
1283 ]]
1284
1285 table.sort(list, sort_cp_list2)
1286
1287 if has_bast == 1 then
1288 db_bast:close()
1289 end
1290
1291 end
1292 --------- END: group duplicate areas and sort ---------
1293
1294 function print_rooms_areas(list, command)
1295
1296 DebugNote("print_rooms_areas:" .. command .. ":" .. #list)
1297
1298 --reset signature for next search
1299 lastMobSignature = ""
1300
1301
1302 if (USER_show_help == "true") then
1303 ColourNote("Gray", "", "Type '" .. command .. " <Index>' or click link, to go to that item")
1304 ColourNote("Gray", "", " Index Target - Location")
1305 ColourNote("Gray", "", "------------------------------------------------------------------------------")
1306 end
1307
1308 local index = 0
1309 for key, value in ipairs(list) do
1310 local skip = false
1311 local multi = ""
1312 index = index + 1
1313 local qty = ""
1314 if (value.qty > 1) then
1315 qty = string.format("%s * ", value.qty)
1316 end
1317
1318 local mobText = qty .. value.mob
1319 --Note(tostring(value.origMob) .. " " .. tostring(value.sortId) .. " " .. tostring(value.mob))
1320 --local mobText = tostring(value.origMob) .. " " .. value.is_multi_area .. " " .. tostring(value.mob) .. " " .. value.type
1321
1322 local origMob = ""
1323 local include_orig = false
1324 if value.distance == -1 then
1325 --origMob = " d: Unknown"
1326 --include_orig = false
1327 origMob = " unknown"
1328 include_orig = true
1329 elseif value.origMob ~= value.mob and value.distance > 3 then
1330 --origMob = " Dist :" .. tostring(value.origMob) .. " " .. tostring(value.distance)
1331 origMob = " d: " .. tostring(value.distance) .. " " .. tostring(value.origMob)
1332 include_orig = true
1333 elseif value.origMob ~= value.mob and value.distance > 0 then
1334 --origMob = " Dist:" .. tostring(value.distance)
1335 origMob = " d: " .. tostring(value.distance)
1336 include_orig = true
1337 end
1338 -- build the kill count info off the bast database
1339 local display_kills = tostring(value.bast_kills)
1340 --[[
1341 if value.distance == -1 then
1342 display_kills = -1
1343 end
1344 ]]
1345 -- build the output for room and area
1346 local bast_len = 1
1347 if value.type == "area" then bast_len = 12 end
1348 local bast = padRight(" k: " .. display_kills ,bast_len, " ")
1349
1350 local deadFlag = false
1351 if (value.isDead ~= nil and value.isDead ~= "") then
1352 mobText = mobText .. " [Dead]"
1353 deadFlag = true
1354 end
1355 --zhal
1356 --DebugNote("xcp_index_line_end:" .. value.mob)
1357 local link
1358 local color
1359 if (value.type == "area") then
1360 link = string.format("~~ %s %s - %s",
1361 padRight(key, 6, " "),
1362 padRight(mobText, 20, " "),
1363 padRight(value.areaId, 12, " ")
1364 )
1365
1366 --link = string.format("~~~ %s %s - %s", padRight(key, 6, " "), padRight(mobText, 20, " "), padRight(value.areaId, 12, " "))
1367 if (deadFlag == false) then
1368 color = "Snow"
1369 else
1370 color = "DimGray"
1371 end
1372 elseif (value.type == "room") then
1373 link = string.format("~~ %s %s - '%s' (%s) - %s [%s-%s]",
1374 padRight(key, 6, " "),
1375 padRight(mobText, 20, " "),
1376 value.roomName,
1377 padRight(value.roomId, 5, " "),
1378 value.areaId,
1379 value.min, value.max
1380 )
1381 if (deadFlag == false) then
1382 color = "lightblue"
1383 else
1384 color = "DimGray"
1385 end
1386 else -- unknown
1387 link = string.format("~ %s%s - '%s' is Unknown",
1388 padRight(key, 5, " "),
1389 padRight(mobText, 26, " "),
1390 value.roomName
1391 )
1392 if (deadFlag == false) then
1393 color = "Crimson"
1394 else
1395 color = "DarkRed"
1396 end
1397 end
1398
1399 -- create colours for cp/gq list outut default will be dead and you are not in current area
1400 local cDefault, cMobName, cRoomName,cRoomId,cAreaId,cMinMax,cBast,cNotes, cBackground =
1401 "DimGray", "DimGray", "DimGray", "DimGray", "DimGray", "DimGray", "DimGray", "DimGray", "black"
1402 -- what you see if the person isn't dead
1403 if (deadFlag == false) then
1404 cDefault = "white"
1405 cMobName = "white"
1406 cRoomName = "orange"
1407 cRoomId = "yellow"
1408 cAreaId = "lime"
1409 cMinMax = "snow"
1410 cBast = "slateblue"
1411 cNotes = "linen"
1412 cBackground = "black"
1413 end
1414 local noUnderline = true
1415 -- override if in current area
1416 if (currentRoom.areaid == value.areaId) and (deadFlag == false) then
1417 cMobName = "yellow"
1418 cRoomName = "lime"
1419 cAreaId = "white"
1420 --noUnderline = false
1421 end
1422
1423 if value.type ~= "room" and value.type ~= "area" then
1424 -- must be unknown
1425 --Note(value.mob .. " " .. value.type)
1426 Hyperlink(command .. " " .. key, link, "Start CP item " .. key, color, cBackground, 0, noUnderline)
1427 else
1428
1429 Hyperlink(command .. " " .. key, "~ " .. padRight(key, 5, " "), "Start CP item " .. key, cDefault, cBackground, 0, noUnderline)
1430
1431 Hyperlink(command .. " " .. key, padRight(mobText, 26, " "), "Start CP item " .. key, cMobName, cBackground, 0, noUnderline)
1432
1433 -- build output for just room
1434 if (value.type == "room") then
1435
1436 Hyperlink(command .. " " .. key, " - " .. padRight(value.areaId, 0, " "), "Start CP item " .. key, cAreaId, cBackground, 0, noUnderline)
1437
1438 Hyperlink(command .. " " .. key, " - '" .. value.roomName .. "'", "Start CP item " .. key, cRoomName, cBackground, 0, noUnderline)
1439
1440 Hyperlink(command .. " " .. key, " " .. padRight(" (" .. value.roomId .. ")", 5, " "), "Start CP item " .. key, cRoomId, cBackground, 0, noUnderline)
1441
1442
1443 local min_max = ""
1444 if (value.type == "room") then
1445 min_max = " [" .. value.min .. "-" .. value.max .. "]"
1446 end
1447 Hyperlink(command .. " " .. key, min_max, "Start CP item " .. key, cMinMax, cBackground, 0, noUnderline)
1448 if has_bast == 1 then
1449 Hyperlink(command .. " " .. key , bast, "Start CP item " .. key, cBast, cBackground, 0, noUnderline)
1450 end
1451
1452 -- build output for just area
1453 elseif value.type == "area" then
1454
1455 Hyperlink(command .. " " .. key, " - " .. padRight(value.areaId, 12, " "), "Start CP item " .. key, cAreaId, cBackground, 0, noUnderline)
1456 if has_bast == 1 then
1457 Hyperlink(command .. " " .. key , bast, "Start CP item " .. key, cBast, cBackground, 0, noUnderline)
1458 end
1459
1460 Hyperlink("roomnote area " .. value.areaId , " [notes]", "Show notes for " .. key, cNotes , cBackground, 0,noUnderline)
1461 end
1462 if include_orig then
1463 Hyperlink(command .. " " .. key , origMob, "Start CP item " .. key, cBast, cBackground, 0, noUnderline)
1464 end
1465 end
1466 print("")
1467
1468 if currentRoom.roomid == value.roomId then
1469 ColourNote("darkorange", "", " You are in room (","yellow","",value.roomId,"DarkOrange","",") for mob: ","lime","", value.mobText)
1470 end
1471 end
1472
1473 if (index == 0) then
1474 ColourNote("darkorange", "", " No campaign items to show.")
1475 end
1476
1477 if (USER_show_help == "true") then
1478 ColourNote("Gray", "", "------------------------------------------------------------------------------")
1479 end
1480
1481 end
1482
1483
1484 function xcp_index_line_end(name, line, wildcards)
1485 if #cpList > 0 then clean_list(cpList) end
1486 DebugNote("xcp_index_line_end")
1487
1488 EnableTrigger("trg_xcp_line", false)
1489 EnableTrigger("trg_xcp_line_end", false)
1490
1491 if (xcp_flag == false) then
1492 return
1493 end
1494 xcp_flag = false
1495 if name == "xcp_not_on_cp" or name == "xcp_wait_on_cp" then
1496 -- not on a campaign based on these messages after requesting one
1497 onCp = false
1498 else
1499 -- add by Zhal
1500 --[[
1501 if #cpList > 0 then
1502 -- table.sort(cpList, sort_cp_list)
1503 end
1504 ]]
1505
1506 print_rooms_areas(cpList, "xcp")
1507 end
1508
1509 -- broadcast this data for other plugins to consume
1510 local ser = serialize.save_simple(cpList)
1511 --print(ser)
1512 BroadcastPlugin(669, ser)
1513
1514 end
1515
1516
1517 function goto_number(name, line, wildcards)
1518 DebugNote("goto_number: " .. wildcards.id)
1519
1520 if (wildcards.id == nil or wildcards.id == "") then
1521 gotoIndex = 1
1522 else
1523 gotoIndex = tonumber(wildcards.id)
1524 end
1525
1526 if (gotoList[gotoIndex] ~= nil) then
1527 if (tonumber(gotoList[gotoIndex]) == nil) then
1528 -- go to an area
1529 Execute("xrt " .. gotoList[gotoIndex])
1530 else
1531 --Note("other")
1532 DebugNote("goto_number matched room: " .. tostring(gotoList[gotoIndex]))
1533 next_room = gotoList[gotoIndex]
1534 goto_roomid(gotoList[gotoIndex])
1535 end
1536 else
1537 ColourNote("darkorange", "", "No destination exists")
1538 end
1539 end
1540
1541 function goto_roomid(roomid)
1542
1543 local dest_in_vidblain = is_vidblain_area(roomid)
1544 local both_in_vidblain = dest_in_vidblain and is_vidblain_area(currentRoom.roomid)
1545
1546
1547 if (dest_in_vidblain == true and both_in_vidblain == false) then
1548 Execute("xmapper move 11910")
1549 Execute("enter hole")
1550
1551 local func = function() Execute("xmapper move " .. roomid) end
1552 execute_in_area("vidblain_hack", "vidblain", func)
1553
1554 else
1555 Execute("xmapper move " .. roomid)
1556 end
1557 end
1558
1559 local is_vidblain_area_sql =
1560 "SELECT area " ..
1561 "FROM rooms " ..
1562 "WHERE uid = %s "
1563
1564 function is_vidblain_area(roomid)
1565
1566 if (USER_check_vidblain == "false") then
1567 return false
1568 end
1569
1570 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1571 local db = assert(sqlite3.open(worldPath .. ".db"))
1572
1573 local select = string.format (is_vidblain_area_sql, fixsql(roomid))
1574 for row in db:nrows(select) do
1575 --Note(row.area)
1576 local areaid = row.area
1577 if (areaid == "vidblain" or
1578 areaid == "imperial" or
1579 areaid == "darklight" or
1580 areaid == "sendhian" or
1581 areaid == "omentor") then
1582
1583 db:close_vm()
1584 return true
1585 end
1586 end
1587 db:close_vm()
1588
1589 return false
1590
1591 end
1592
1593 function goto_next(name, line, wildcards)
1594 DebugNote("next:" .. next_room .. ":" .. currentRoom.roomid)
1595 if (tonumber(next_room) == tonumber(currentRoom.roomid)) then
1596 gotoIndex = gotoIndex + 1
1597 end
1598
1599 if (gotoList[gotoIndex] ~= nil) then
1600
1601 ColourNote("darkorange", "", "Goto - " .. gotoIndex .. " of " .. #gotoList)
1602 next_room = gotoList[gotoIndex]
1603 Execute("xmapper move " .. next_room)
1604 else
1605 ColourNote("darkorange", "", "No destination exists")
1606 end
1607 end
1608
1609 function goto_cp(name, line, wildcards)
1610
1611 listIndex = tonumber(wildcards.index)
1612 mode = "cp"
1613
1614 DebugNote("goto_cp:" .. wildcards.index)
1615
1616 BroadcastPlugin(670, "cp")
1617
1618 goto_list_item(cpList, listIndex)
1619
1620 end
1621
1622 -- v3 --
1623 function goto_gq(name, line, wildcards)
1624
1625 gqIndex = tonumber(wildcards.index)
1626 mode = "gq"
1627
1628 DebugNote("goto_gq:" .. wildcards.index)
1629
1630 BroadcastPlugin(670, "gq")
1631
1632 goto_list_item(gqList, gqIndex)
1633
1634 end
1635
1636 function goto_list_item(list, index)
1637
1638 -- reset room list
1639 gotoList = {}
1640 gotoIndex = 1
1641
1642 local localItem = list[index]
1643 local localRoom = currentRoom
1644
1645 if (localItem ~= nil and localRoom ~= nil and localRoom.areaid ~= nil) then
1646
1647 -- send this mob name to S&D plugin
1648 -- why is localitem blank sometimes?
1649 DebugTPrint("goto_list_item - localItem", localItem)
1650
1651 if (localItem.type == "area") then
1652 DebugNote("area type")
1653 remote_guess_mob_name(localItem.mob, localItem.areaId, true)
1654 local func = function()
1655 -- added once gq mobs became eligible to hunt i.e., fooling hunt trick
1656 if #gqList == 0 or onGq == false then
1657 Execute("x_ht " .. localItem.mob)
1658 --Execute("x_qw " .. localItem.mob)
1659 else
1660 -- michael
1661 Execute("x_qw " .. localItem.mob)
1662 end
1663 end
1664
1665
1666 if localItem.landingRoom > 0 then
1667 Note("gooo mapper goto " .. localItem.landingRoom)
1668 Execute("mapper goto " .. localItem.landingRoom)
1669
1670 elseif (localRoom.areaid ~= localItem.areaId) then
1671 Execute("xrt " .. localItem.areaId)
1672 end
1673
1674 execute_in_area("goto_list_item_area", localItem.areaId, func)
1675
1676 else -- "room"
1677 DebugNote("room type")
1678 remote_guess_mob_name(localItem.mob, localItem.areaId, true)
1679
1680 search_rooms(localItem.roomName .. "|" .. localItem.areaId, "area", localItem.mob)
1681
1682 end
1683 else
1684 ColourNote("darkorange", "", "No item exists, or data busy (try again)")
1685 end
1686
1687 end
1688
1689 local xrun_to_sql_uid =
1690 "SELECT r.uid, r.name as room, r.area " ..
1691 "FROM rooms r " ..
1692 "WHERE r.area like %s " ..
1693 "ORDER BY r.name "
1694
1695 local xrun_to_sql_name =
1696 "SELECT r.uid, r.name as room, r.area " ..
1697 "FROM rooms r " ..
1698 "INNER JOIN areas a ON a.uid = r.area " ..
1699 "WHERE r.area like %s OR a.name like %s " ..
1700 "ORDER BY r.name "
1701
1702 function xrun_to(name, line, wildcards)
1703 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1704 local db = assert(sqlite3.open(worldPath .. ".db"))
1705
1706 -- HACK for ftii
1707 if (wildcards[1] == "ft2") then
1708 wildcards[1] = "ftii"
1709 end
1710
1711 -- Check for xset marked room
1712 local startRoom = get_start_room(wildcards[1])
1713 if (startRoom ~= -1) then
1714 -- start room has been marked, we are done here
1715 ColourNote("darkorange", "", "x-runto (" .. startRoom .. ") xset marked as start room")
1716 goto_roomid(startRoom)
1717 else
1718 -- Room has not been marked for the area
1719 -- Search mapper DB for room with lowest id for the area
1720
1721 -- try exact hit first
1722 local select = string.format (xrun_to_sql_uid, fixsql(wildcards[1]))
1723 DebugNote("xrun_to (1)- " .. select)
1724
1725 for row in db:nrows(select) do
1726 ColourNote("darkorange", "", "x-runto (" .. row.uid .. ") " .. row.room .. " in " .. row.area .. " - exact match")
1727
1728 goto_roomid(row.uid)
1729
1730 db:close_vm()
1731 return
1732 end
1733 db:close_vm()
1734
1735 -- try a wildcard match
1736 local like = fixsql("%" .. wildcards[1] .. "%")
1737 select = string.format (xrun_to_sql_name, like, like)
1738 DebugNote("xrun_to (2)- " .. select)
1739
1740 for row in db:nrows(select) do
1741 ColourNote("darkorange", "", "x-runto (" .. row.uid .. ") " .. row.room .. " in " .. row.area .. " - 'like' match")
1742
1743 goto_roomid(row.uid)
1744
1745 db:close_vm()
1746 return
1747 end
1748 db:close_vm()
1749
1750 ColourNote("darkorange", "", "No matching rooms found. Using aardwolf runto...")
1751 Execute("xmapper move 32418") -- recall
1752 Execute("runto " .. wildcards[1])
1753 end
1754 end
1755
1756 function xset_pk(name, line, wildcards)
1757
1758 if (showPK == "true") then
1759 showPK = "false"
1760 else
1761 showPK = "true"
1762 end
1763
1764 SetVariable("showPK", showPK)
1765 ColourNote("DarkOrange", "", "Show PK room flag : " .. showPK)
1766
1767 end
1768
1769 function xset_to_mark(name, line, wildcards)
1770 areaStartRooms[currentRoom.areaid] = { areaname = currentRoom.areaname, roomid = currentRoom.roomid }
1771 ColourNote("darkorange", "", currentRoom.roomid .. " set as starting room for " .. currentRoom.areaid)
1772 SetVariable("areaStartRooms", serialize.save_simple(areaStartRooms))
1773 end
1774
1775 function get_start_room(area)
1776 local cleanedArea = string.lower(area)
1777 if (areaStartRooms[cleanedArea] ~= nil) then
1778 -- exact match on area id
1779 return areaStartRooms[cleanedArea].roomid
1780 end
1781
1782 for key, val in pairs(areaStartRooms) do
1783 if (string.match(string.lower(key), cleanedArea) ~= nil) then
1784 -- string match on key
1785 return val.roomid
1786 elseif val.areaname ~= nil and (string.match(string.lower(val.areaname), cleanedArea) ~= nil) then
1787 -- string match on area name
1788 return val.roomid
1789 end
1790 end
1791
1792 -- found nothing
1793 return -1
1794 end
1795
1796 ---- room notes --------
1797
1798 function room_note_area(name, line, wildcards)
1799 if (wildcards.areaid == "") then
1800 get_notes(currentRoom.areaid, nil)
1801 else
1802 get_notes(wildcards.areaid, nil)
1803 end
1804 end
1805
1806 function room_note(name, line, wildcards)
1807 get_notes(nil, currentRoom.roomid)
1808 end
1809
1810 function get_notes(areaid, roomid, text_only)
1811
1812 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1813 local db = assert(sqlite3.open(worldPath .. ".db"))
1814
1815 local sql = " SELECT b.uid, b.notes "
1816 sql = sql .. " FROM bookmarks b "
1817 if (areaid ~= nil) then
1818 sql = sql .. " INNER JOIN rooms r ON b.uid = r.uid "
1819 sql = sql .. " WHERE r.area = " .. fixsql(areaid)
1820 else
1821 sql = sql .. " WHERE b.uid = " .. fixsql(roomid)
1822 end
1823 sql = sql .. " ORDER BY b.uid "
1824 DebugNote(sql)
1825
1826 local index = 0
1827
1828 if (areaid ~= nil) then
1829 Simulate("\nNotes for " .. getAreaName(areaid) .. "\n")
1830 end
1831
1832 for row in db:nrows(sql) do
1833 index = index + 1
1834 if (text_only == true) then
1835 local line = string.format(" note:'%s'", row.notes)
1836 Hyperlink("xmapper move " .. row.uid, line, "go to room " .. row.uid, "lightblue", "black", 0, true)
1837 else
1838 local line = string.format(" (%s) %s", row.uid, row.notes)
1839 Hyperlink("xmapper move " .. row.uid, line, "go to room " .. row.uid, "lightblue", "black", 0, true)
1840 print("")
1841 end
1842 end
1843 db:close_vm()
1844 if (areaid ~= nil and index == 0 and text_only ~= true) then
1845 Simulate("\tNo notes.\n")
1846 end
1847 end
1848
1849
1850
1851 function getRoomByMob(mobName)
1852 -- unused
1853 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1854 local db = assert(sqlite3.open(worldPath .. ".db"))
1855
1856 local sql = "SELECT roomid, mobname, count "
1857 sql = sql .. "FROM mobs "
1858 sql = sql .. "WHERE mobname = %s "
1859 sql = sql .. "ORDER BY count desc "
1860 for row in db:nrows(string.format (sql, fixsql(uid))) do
1861 db:close_vm()
1862 return row.name
1863 end
1864 db:close_vm()
1865 end
1866
1867
1868 function getAreaName(uid)
1869 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1870 local db = assert(sqlite3.open(worldPath .. ".db"))
1871
1872 local sql = "SELECT name FROM areas WHERE uid = %s"
1873 for row in db:nrows(string.format (sql, fixsql(uid))) do
1874 db:close_vm()
1875 return row.name
1876 end
1877 db:close_vm()
1878
1879 return uid
1880 end
1881
1882 function getAreaUid(name)
1883
1884 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1885 local db = assert(sqlite3.open(worldPath .. ".db"))
1886
1887 local sql = "SELECT uid FROM areas WHERE name = %s order by uid "
1888
1889 local areas = {}
1890 local index = 0
1891 DebugNote("getAreaUid:" .. fixsql(name))
1892 for row in db:nrows(string.format (sql, fixsql(name))) do
1893 DebugNote(row.uid .. ":" .. name)
1894 index = index + 1
1895 areas[index] = {uid = row.uid, name = name}
1896 end
1897
1898 db:close_vm()
1899 return areas
1900 end
1901
1902
1903 function map_area(name, line, wildcards)
1904 if wildcards.mob == "" or wildcards.mob == nil then
1905 search_exact = false
1906 else
1907 search_exact = true
1908 end
1909 search_rooms(wildcards.loc, 'area', wildcards.mob)
1910 end
1911
1912 function map_area_all(name, line, wildcards)
1913 search_rooms(wildcards.loc .. "|all", 'all', wildcards.mob)
1914 end
1915
1916 local search_rooms_sql =
1917 "SELECT r.uid as uid, r.name as name, info, r.area as area, " ..
1918 "ifnull(a.name, r.area) as area_name, 1 as DisplayOrder " ..
1919 "FROM rooms r " ..
1920 "LEFT OUTER JOIN areas a ON r.area = a.uid " ..
1921 "WHERE r.name = %s " ..
1922 "AND (%s = 'all' OR (a.name = %s OR r.area = %s)) " ..
1923
1924 "UNION " ..
1925
1926 "SELECT r.uid, r.name, info, r.area, " ..
1927 "ifnull(a.name, r.area) as area_name, 0 as DisplayOrder " ..
1928 "FROM rooms r " ..
1929 "LEFT OUTER JOIN areas a ON r.area = a.uid " ..
1930 "WHERE r.name <> %s " ..
1931 "AND r.name LIKE %s " ..
1932 "AND (%s = 'all' OR (a.name = %s OR r.area = %s)) " ..
1933 "ORDER BY Area, DisplayOrder DESC "
1934
1935 function search_rooms(room, searchType, fullMobName)
1936
1937 DebugNote("search_rooms(" .. room .."," .. searchType .. "," .. fullMobName .. ")")
1938
1939 if (room == nil or room == "") then
1940 Note("map_area() error : room is not known")
1941 return
1942 end
1943
1944 -- room|area
1945 local parts = split(room, "[^|]+") -- pipe delimited
1946 local room = parts[1]
1947 local area_id
1948 if (#parts == 2) then
1949 area_id = parts[2]
1950 else
1951 if (currentRoom ~= nil) then
1952 area_id = currentRoom.areaid
1953 else
1954 ColourNote("darkorange", "", "Area not known, falling back to mapper list")
1955 Execute("mapper list " .. parts[1])
1956 end
1957 end
1958
1959 if (room == nil) then
1960 Note("map_area() - Room not known")
1961 return
1962 end
1963 Note("here")
1964
1965 if search_exact then
1966 --Note("exact")
1967 -- use this to return exact match of room name
1968 like = room
1969 else
1970 --Note("not exact")
1971 -- use this stmt if you want to return rooms with similar names
1972 like = "%"..room.."%"
1973 end
1974
1975 -- i forget what this does? Strip out a leading " ?
1976 --if string.sub(room,1,1) == "\"" and string.sub(room,-1) == "\"" then
1977 -- like = string.sub(room,2,-2)
1978 --end
1979
1980 local select = string.format(search_rooms_sql,
1981 fixsql(room),
1982 fixsql(area_id),
1983 fixsql(area_id),
1984 fixsql(area_id),
1985 fixsql(room),
1986 fixsql(like),
1987 fixsql(area_id),
1988 fixsql(area_id),
1989 fixsql(area_id))
1990 DebugNote(select)
1991
1992 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1993 local db = assert(sqlite3.open(worldPath .. ".db"))
1994
1995 local results = {}
1996 local roomid_list = {}
1997
1998 for row in db:nrows(select) do
1999 -- sanitize text room ids for "unmappable" rooms that are now being mapped
2000 local id = (tonumber(row.uid) or -1)
2001 -- make safe against bad dbs
2002 local areaid_lookup = row.area or row.area_name
2003 local full_mobName = string.lower(fullMobName)
2004
2005 local bast_kills = mob_count(full_mobName,areaid_lookup,id)
2006 --Note(fullMobName .. " " .. areaid_lookup .. " " .. id)
2007 results[#results + 1] = {
2008 uid = id,
2009 name = row.name,
2010 info = row.info,
2011 area = row.area_name,
2012 areaid = areaid_lookup,
2013 mob = fullMobName,
2014 bast_kills = bast_kills
2015
2016 }
2017 -- make a list of room ids zhal this goes nowhere
2018 if (id > 0) then
2019 roomid_list[#roomid_list + 1] = id
2020 end
2021
2022 end -- finding rooms
2023 db:close_vm()
2024
2025
2026 local mob_mapping = {}
2027
2028 local freq_total = mob_mapping[-1] or 0
2029 DebugNote("freq_total:" .. freq_total)
2030
2031 -- add mob to room mapping
2032 for key, value in ipairs(results) do
2033
2034 local freq = mob_mapping[value.uid]
2035 if (freq ~= nil) then
2036 value.freq = math.floor((freq / freq_total) * 100)
2037 else
2038 value.freq = 0
2039 end
2040 end
2041
2042 table.sort(results, sort3_func)
2043
2044 print_rooms(results)
2045 end
2046
2047 function IPRINT_ROOMS(json)
2048 -- load serialize.save_simple data
2049 luastmt = "gPrintRooms = " .. json
2050 assert (loadstring (luastmt or "")) ()
2051
2052 print_rooms(gPrintRooms)
2053 end
2054
2055 -- uses results{ areaid, area, info, name, uid, freq }
2056 function print_rooms(results)
2057 -- print results
2058 gotoList = {}
2059 mapper_area_index = 0
2060 local last_area = ""
2061
2062 DebugTPrint("results", results)
2063
2064 if (USER_show_help == "true") then
2065 ColourNote("Gray", "", "Type 'go <Index>' or click link, to go to that room")
2066 ColourNote("Gray", "", " Index Room Name (uid)")
2067 ColourNote("Gray", "", "-------------------------------------------------")
2068 end
2069
2070 for key, value in ipairs(results) do
2071 DebugNote("area: " .. value.areaid )
2072 --Note("gmcp vs script " .. tostring(currentRoom.roomid) .. " vs " .. tostring(value.uid))
2073 -- create colors
2074 -- this is default, which is when you are in the same room
2075 local cBackground,cIndex,cRoomName,cRoomId,cBast,cDirections = "whitesmoke", "black", "black", "black", "black", "black"
2076 if tostring(currentRoom.roomid) ~= tostring(value.uid) then
2077 -- you are not in the same room
2078 cBackground = "black"
2079 cIndex = "white"
2080 cRoomName = "white"
2081 cRoomId = "yellow"
2082 cBast = "white"
2083 cDirections = "white"
2084 end
2085
2086 if (last_area ~= value.areaid) then
2087 -- michael
2088 local min = (area_range[value.area_name] or {min = 0}).min
2089 local max = (area_range[value.area_name] or {max = 300}).max
2090 local min_max = "[" .. min .. "-" .. max .. "]"
2091
2092 if (mapper_area_index == 0) then
2093 -- first line
2094 -- mapper_area_index <-- idk why bast had thi in the next line
2095 local areaLine = string.format(" %s %s",min_max, value.areaid)
2096 -- header that shows above hunt trick. No need to change color, used to be silver
2097 Hyperlink("go " .. mapper_area_index, areaLine, "go to area (go) " .. value.areaid, "darkorange", "black", 0)
2098 gotoList[mapper_area_index] = value.areaid
2099 mapper_area_index = mapper_area_index + 1
2100 else
2101 Note("")
2102 -- when multiple areas appear, e.g., search all database and multiple areas appear (xmall blah)
2103 -- could make this brighter and maybe even add lvl range
2104 -- area_range.mine and max
2105 --local areaLine = string.format("~~ %s", value.areaid)
2106 local areaLine = string.format(" %s %s",min_max, value.areaid)
2107 Hyperlink("xrt " .. value.areaid, areaLine, "go to area (xrt) " .. value.areaid, "darkorange", "black", 0)
2108 end
2109 print("")
2110 last_area = value.areaid
2111 end
2112
2113 -- v3 --
2114 local isPK = string.find((value.info or ""), "pk") ~= nil
2115 local isPKText = " "
2116 DebugNote("isPK: " .. tostring(isPK))
2117 if (isPK == true and showPK == "true") then
2118 isPKText = "[PK] "
2119 end
2120
2121 -- this is the first thing on the left, the ~~ #
2122 local line1 = string.format("~~ %s ",
2123
2124 padRight(mapper_area_index, 3, " "))
2125
2126 Hyperlink("go " .. mapper_area_index, line1, "go to item ht " .. mapper_area_index, cIndex, cBackground, 0,true)
2127
2128 local line2 = string.format("%s (%s) %s",
2129 padRight(string.gsub(value.name, "@[a-zA-Z]", ""), 20, " "),
2130 value.uid,value.bast_kills)
2131
2132 -- showed as room results and Quick-Where
2133 -- v4 --
2134 -- color isn't changed
2135 local namePad = 25
2136 if isPK then
2137 Hyperlink("go " .. mapper_area_index, isPKText, "go to item (pk) " .. mapper_area_index, "red", cBackground, 0, true)
2138 namePad = 20
2139 end
2140--Note("michael")
2141 local noUnderline = true
2142 local line10 = padRight(string.gsub(value.name, "@[a-zA-Z]", ""), namePad, " ")
2143 local line11 = padRight(" (" .. value.uid .. ")", 2, " ")
2144 local bast = padRight(" Cnt: " .. tostring(value.bast_kills),1, " ")
2145
2146 -- room name
2147 Hyperlink("go " .. mapper_area_index, line10,"go to item line (line 2.2) " .. mapper_area_index,
2148 cRoomName, cBackground, 0, noUnderline)
2149
2150 -- room id #
2151 Hyperlink("go " .. mapper_area_index, line11 , "go to item line (line 2.2) " .. mapper_area_index,
2152 cRoomId, cBackground, 0, noUnderline)
2153
2154 if has_bast == 1 then
2155 -- count of bast kills
2156 Hyperlink("go " .. mapper_area_index, bast, "go to item line (line 2.2) " .. mapper_area_index,
2157 cBast, cBackground, 0,noUnderline)
2158 end
2159 -- original
2160 --Hyperlink("go " .. mapper_area_index, line2, "go to item line (line 2.2) " .. mapper_area_index, "lightblue", "black", 0,noUnderline)-
2161
2162 -- this is at the right of every line. shows speedwalk but doesnt go
2163 Hyperlink("mapper where " .. value.uid,
2164 string.format("%-3s"," {?}"),
2165 "click for speedwalk to this room",
2166 cDirections,
2167 cBackground,
2168 0, noUnderline)
2169 gotoList[mapper_area_index] = value.uid
2170
2171 -- show room notes
2172 DebugNote("get note : " .. value.uid)
2173 get_notes(nil, value.uid, true)
2174
2175 print("")
2176 --ColourTell("","","\n")
2177
2178 mapper_area_index = mapper_area_index + 1
2179 end
2180
2181
2182 if (mapper_area_index == 0) then
2183 ColourNote("darkorange", "", "No matching rooms found.")
2184 end
2185
2186 if (USER_show_help == "true") then
2187 ColourNote("Gray", "", "-------------------------------------------------")
2188 Note("")
2189 end
2190
2191 end
2192
2193 function map_purgeroom (name, line, wildcards)
2194 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
2195 local db = assert(sqlite3.open(worldPath .. ".db"))
2196
2197 Note(string.format ("delete from exits WHERE fromuid = %s;", fixsql(currentRoom.roomid)))
2198 dbcheck (db:execute (string.format ("delete from exits WHERE fromuid = %s;", fixsql(currentRoom.roomid))))
2199 Note(string.format ("delete from exits WHERE touid = %s;", fixsql(currentRoom.roomid)))
2200 dbcheck (db:execute (string.format ("delete from exits WHERE touid = %s;", fixsql(currentRoom.roomid))))
2201 Note(string.format ("delete from rooms_lookup WHERE uid = %s;", fixsql(currentRoom.roomid)))
2202 dbcheck (db:execute (string.format ("delete from rooms_lookup WHERE uid = %s;", fixsql(currentRoom.roomid))))
2203 Note(string.format ("delete from rooms WHERE uid = %s;", fixsql(currentRoom.roomid)))
2204 dbcheck (db:execute (string.format ("delete from rooms WHERE uid = %s;", fixsql(currentRoom.roomid))))
2205 db:close_vm()
2206
2207 ColourNote("darkorange", "", "Purged room (" .. currentRoom.roomid .. ") from the mapper database.")
2208 end
2209
2210 local cp_simulate_toggle = 0
2211 function cp_simulate(name, line, wildcards)
2212
2213 Simulate("\n")
2214
2215 if (cp_simulate_toggle == 0) then
2216 --Simulate("You still have to kill * a slinky sylph (A corner in the bull pen)\n")
2217 Simulate("You still have to kill * a reoging lotus eater (Land of the Lotus-Eaters)\n")
2218 Simulate("You still have to kill * a satyr (The Labyrinth)\n")
2219 --Simulate("You still have to kill * a A mad bird (On A Pinnacle)\n")
2220 -- swirl good one
2221 --Simulate("You still have to kill * a swirl of orange and purple (Fantasy Creek)\n")
2222 --Simulate("You still have to kill * a swirl of orange and purple (Fantasy Creek)\n")
2223 --Simulate("You still have to kill * a patient drow miner (The Amber Mine)\n")
2224 --Simulate("You still have to kill * a giant mosquito (Jungles of Verume)\n")
2225 -- Simulate("You still have to kill * a giant mosquito (Jungles of Verume)\n")
2226 Simulate("You still have to kill * the head necromancer (Necromancers' Guild)\n")
2227 --Simulate("You still have to kill * a transparent gardener (Garden)\n")
2228 --Simulate("You still have to kill * a burst of anger (Anger and Violence)\n")
2229 Simulate("You still have to kill * a centaur stallion (The Labyrinth)\n")
2230 --Simulate("You still have to kill * a field rat (Inside the Northeast Watchtower)\n")
2231 --Simulate("You still have to kill * a shambling mound (The Labyrinth)\n")
2232 Simulate("You still have to kill * a blo ball (Nearing The Top Of The Pathway)\n")
2233 --Simulate("You still have to kill * an adventurous spelunker (An Underground River)\n")
2234 --Simulate("You still have to kill * a chipmunk (The Labyrinth)\n")
2235 Simulate("You still have to kill * a tall peasant (At the bonfire)\n")
2236 Simulate("You still have to kill * Gunnlod (Gunnlod's Home)\n")
2237 --Simulate("You still have to kill * a repairs troll (Observation stands)\n")
2238 --Simulate("You still have to kill * Michael (Blue Roomee)\n")
2239 Simulate("You still have to kill * Prince Rich'Erd (Sho'aram, Castle in the Sand)\n")
2240 Simulate("You still have to kill * Doctor Cameroon " .. [["]] .. "Rusty" .. [["]] .. " Baboon (Canyon Memorial Hospital)\n")
2241 --Note("You still have to kill * Doctor Cameroon " .. [["]] .. "Rusty" .. [["]] .. " Baboon (Canyon Memorial Hospital)")
2242 cp_simulate_toggle = 1
2243 else
2244
2245 Simulate("You still have to kill * a burst of anger (Anger and Violence)\n")
2246 Simulate("You still have to kill * a shambling mound (The Labyrinth)\n")
2247 Simulate("You still have to kill * a swirl of orange and purple (Fantasy Creek)\n")
2248 Simulate("You still have to kill * a field rat (Inside the Northeast Watchtower)\n")
2249 Simulate("You still have to kill * a transparent gardener (Garden)\n")
2250 Simulate("You still have to kill * a slinky sylph (A corner in the bull pen)\n")
2251 Simulate("You still have to kill * a tall peasant (At the bonfire)\n")
2252 cp_simulate_toggle = 0
2253 end
2254 Simulate("Note: Dead means that the target is dead, not that you have killed it.\n")
2255 Simulate("\n")
2256 Simulate("You have 6 days, 23 hours and 56 minutes left to finish this campaign.\n")
2257 Simulate("\n")
2258
2259 end
2260 function cp_simulate1(name, line, wildcards)
2261
2262 Simulate("\n")
2263
2264 if (cp_simulate_toggle == 0) then
2265 --Simulate("You still have to kill * Isscheburqua (Insanitaria)\n")
2266 Simulate("You still have to kill * a satyr (The Labyrinth)\n")
2267 Simulate("You still have to kill * a rook citizen (Avian Kingdom)\n")
2268 Simulate("You still have to kill * Lea, the farmer's daughter (Farmyard)\n")
2269 Simulate("You still have to kill * a rook citizen (Nesting Home)\n")
2270 Simulate("You still have to kill * a demon school student (The School of Horror)\n")
2271 Simulate("You still have to kill * a hookle fish (Black Lagoon)\n")
2272 Simulate("You still have to kill * Harry (Unknown Tower - Dead)\n")
2273 Simulate("You still have to kill * a former court jester (The Labyrinth)\n")
2274 Simulate("You still have to kill * Parent (The Kitchen)\n")
2275 Simulate("You still have to kill * a wealth redistribution specialist (Empyrean, Streets of Downfall)\n")
2276 Simulate("You still have to kill * the reaching thorns (Eternal Autumn)\n")
2277 Simulate("You still have to kill * Redtooth (Mossflower Wood - Dead)\n")
2278 Simulate("You still have to kill * Castle Guard (Rebellion of the Nix)\n")
2279 Simulate("You still have to kill * Jules (The Amazon Nation)\n")
2280 Simulate("You still have to kill * an earth fiend (The Broken Halls of Horath)\n")
2281 Simulate("You still have to kill * the spirit of Bakarne (The Empire of Aiighialla)\n")
2282 Simulate("You still have to kill * Elfgar Sous-Fled (Some Place)\n")
2283 Simulate("You still have to kill * the heart of a sandstorm (Living Mines of Dak'Tai)\n")
2284 cp_simulate_toggle = 1
2285 else
2286 Simulate("You still have to kill * a former court jester (The Labyrinth)\n")
2287 Simulate("You still have to kill * the heart of a sandstorm (Buried in the Great Desert's unrelenting dunes)\n")
2288 Simulate("You still have to kill * Parent (The Kitchen)\n")
2289 Simulate("You still have to kill * a rhino seraph (A Corridor of Cinnamon and Silver)\n")
2290 Simulate("You still have to kill * A sprite prisoner (A cell)\n")
2291
2292 cp_simulate_toggle = 0
2293 end
2294 Simulate("Note: Dead means that the target is dead, not that you have killed it.\n")
2295 Simulate("\n")
2296 Simulate("You have 6 days, 23 hours and 56 minutes left to finish this campaign.\n")
2297 Simulate("\n")
2298
2299 end
2300 function cp_simulate2(name, line, wildcards)
2301
2302 Simulate("\n")
2303
2304 if (cp_simulate_toggle == 0) then
2305 Simulate("You still have to kill * a practicing demon (The Arena)\n")
2306 Simulate("You still have to kill * Savinga, prince of death (In the clouds)\n")
2307 Simulate("You still have to kill * the cell keeper (A Hallway of Cells)\n")
2308 Simulate("You still have to kill * the ghost (The Silver Volcano)\n")
2309 Simulate("You still have to kill * Gabried, archangel of fire (In the clouds)\n")
2310 Simulate("You still have to kill * a demon berserker (On the Floor of the Arena)\n")
2311 Simulate("You still have to kill * the storm spirit (Storm Ships of Lem-Dagor)\n")
2312 Simulate("You still have to kill * Valefor, prince od theft (The Flying Citadel)\n")
2313 Simulate("You still have to kill * a huge Wave runner sergeant (The Storm Cruiser, Tempest)\n")
2314 Simulate("You still have to kill * a giggling girl (Inside Pumice Library)\n")
2315 Simulate("You still have to kill * a demon soldier (In the Stands surrounding the Arena)\n")
2316 Simulate("You still have to kill * Trey, the Unforgiven (A Hidden Den)\n")
2317 Simulate("You still have to kill * Prince Rich'Erd (Sho'aram, Castle in the Sand)\n")
2318 Simulate("You still have to kill * Doctor Cameroon " .. [["]] .. "Rusty" .. [["]] .. " Baboon (Canyon Memorial Hospital)\n")
2319 cp_simulate_toggle = 1
2320 else
2321 Simulate("You still have to kill * a former court jester (The Labyrinth)\n")
2322 Simulate("You still have to kill * the heart of a sandstorm (Buried in the Great Desert's unrelenting dunes)\n")
2323 Simulate("You still have to kill * a barber (The Labyrinth)\n")
2324 Simulate("You still have to kill * Parent (The Kitchen)\n")
2325 Simulate("You still have to kill * a rhino seraph (A Corridor of Cinnamon and Silver)\n")
2326 Simulate("You still have to kill * A sprite prisoner (A cell)\n")
2327
2328 cp_simulate_toggle = 0
2329 end
2330 Simulate("Note: Dead means that the target is dead, not that you have killed it.\n")
2331 Simulate("\n")
2332 Simulate("You have 6 days, 23 hours and 56 minutes left to finish this campaign.\n")
2333 Simulate("\n")
2334
2335 end
2336 -------- Area level capture -------
2337
2338
2339 --Commander Barcett tells you ' Good luck in your campaign!''
2340
2341 function area_index_start_gag(name, line, wildcards)
2342 DebugNote("area_index_start_gag - " .. wildcards[1] .. ":" .. wildcards[2])
2343 if (wildcards[1] == "0" and wildcards[2] == "298") then
2344 EnableTrigger("trg_area_index_start", true)
2345 EnableTrigger("trg_area_index_line", false)
2346 EnableTrigger("trg_area_index_end", false)
2347 EnableTrigger("trg_area_index_gag1", true)
2348 EnableTrigger("trg_area_index_gag2", true)
2349 else -- not an area index command
2350 EnableTrigger("trg_area_index_start", false)
2351 EnableTrigger("trg_area_index_line", false)
2352 EnableTrigger("trg_area_index_end", false)
2353 EnableTrigger("trg_area_index_gag1", false)
2354 EnableTrigger("trg_area_index_gag2", false)
2355 end
2356 end
2357
2358 function area_index_start(name, line, wildcards)
2359 DebugNote("area_index_start")
2360 EnableTrigger("trg_area_index_start", false)
2361 EnableTrigger("trg_area_index_line", true)
2362 EnableTrigger("trg_area_index_end", true)
2363
2364 area_range = {}
2365
2366 ColourNote("DarkOrange", "", "*** Indexing area levels...")
2367 end
2368
2369 function area_index_line(name, line, wildcards)
2370 DebugNote("area_index_line")
2371
2372 area_range[Trim(wildcards.area)] = {
2373 area = Trim(wildcards.area),
2374 min = tonumber(Trim(wildcards.min)),
2375 max = tonumber(Trim(wildcards.max)),
2376 lock = tonumber(Trim(wildcards.lock)) or 0 }
2377 --tprint(area_range[wildcards.area])
2378
2379 end
2380
2381 function area_index_end(name, line, wildcards)
2382 DebugNote("area_index_end")
2383
2384 EnableTrigger("trg_area_index_start", false)
2385 EnableTrigger("trg_area_index_line", false)
2386 EnableTrigger("trg_area_index_end", false)
2387 EnableTrigger("trg_area_index_gag1", false)
2388 EnableTrigger("trg_area_index_gag2", false)
2389
2390 ColourNote("DarkOrange", "", "*** Area levels indexed!")
2391
2392 DoAfterSpecial(2, "xset resume page size", sendto.execute)
2393
2394 SetVariable("areas_serial", serialize.save( "areas_ser", area_range ))
2395 Execute("cp check")
2396 end
2397
2398 function clean_sql(val)
2399 val = string.gsub(val , "'", "''")
2400 return val
2401 end
2402 -------- GQ ---------
2403 -- v2 --
2404
2405 function capture_gq_line(name, line, args)
2406
2407 EnableTrigger("x_gq_line_end", true)
2408
2409 if (gqList == nil) then
2410 gqList = {}
2411 gqIndex = 1
2412 end
2413
2414 --gqIndex = get_rooms_areas(gqList, gqIndex, wildcards.where, wildcards.mob, wildcards.qty)
2415 get_rooms_areas(gqList, args.where, args.mob, args.qty, "","gq")
2416
2417 end
2418
2419 function capture_gq_line_finished(name, line, wildcards)
2420 DebugNote("capture_gq_line_finished")
2421 EnableTriggerGroup("x_gq", false)
2422
2423 gqList = {}
2424 onGq = false
2425 -- broadcast this data for other plugins to consume
2426 local ser = serialize.save_simple(gqList)
2427 --print(ser)
2428 BroadcastPlugin(667, ser)
2429 end
2430
2431 function capture_gq_line_end(name, line, wildcards)
2432
2433 DebugNote("capture_gq_line_end")
2434
2435 EnableTriggerGroup("x_gq", false)
2436 clean_list(gqList)
2437 --[[
2438 if #gqList > 0 and has_bast == 1 then
2439 table.sort(gqList, sort_cp_list)
2440 end
2441 ]]
2442 print_rooms_areas(gqList, "qq")
2443
2444 if #gqList == 0 then onGq = false end
2445 -- broadcast this data for other plugins to consume
2446 local ser = serialize.save_simple(gqList)
2447 --print(ser)
2448 BroadcastPlugin(667, ser)
2449 end
2450
2451 local test_toggle = 0
2452
2453 function gq_list (name, line, wildcards)
2454
2455 gqList = {}
2456 gqList_old = gqList
2457 gqIndex = 1
2458
2459 EnableTrigger("x_gq_line", true)
2460 onGq = true
2461 if has_bast then
2462 Execute("gq check")
2463 else
2464 Send("gq c")
2465 end
2466 end
2467
2468 function gq_list_simulate (name, line, wildcards)
2469
2470 gqList = {}
2471 gqIndex = 1
2472 onGq = true
2473 EnableTrigger("x_gq_line", true)
2474
2475 if (test_toggle == 0) then
2476 Simulate("\nYou still have to kill 1 * A kicking patient (A FAKE-private room)\n")
2477 Simulate("You still have to kill 1 * A snoring patient (Canyon Memorial Hospital)\n")
2478 Simulate("You still have to kill 1 * Sergeant Steel (The Armory)\n")
2479 Simulate("You still have to kill 1 * An abominable snowman (The Snowy Path)\n")
2480 Simulate("You still have to kill 1 * The senior assassin (Assassins' Scrying Chamber)\n")
2481 Simulate("You still have to kill 1 * Lord Kyron (The DarkLight)\n")
2482 Simulate("You still have to kill 1 * Buck (Imperial Nation)\n")
2483 Simulate("You still have to kill 1 * Bjorn (Realm of the Firebird)\n")
2484 Simulate("You still have to kill 2 * a crow (Realm of the Firebird)\n")
2485 Simulate("You still have to kill 2 * a gate guard (Realm of the Firebird)\n")
2486 Simulate("You still have to kill 1 * Destroyer of Minds (Deathtrap Dungeon)\n")
2487 Simulate("You still have to kill 1 * Rudolph (In the Air)\n")
2488 Simulate("You still have to kill 1 * a tester of fire (The experimenting room (Fire))\n")
2489 Simulate("You still have to kill 2 * a Bad Apple (Umari's Castle)\n")
2490 Simulate("You still have to kill 1 * the third little pig (Pig Pen)\n\n")
2491
2492 test_toggle = 1
2493 elseif (test_toggle == 1) then
2494 -- TODO add 1 room and others area test here
2495 Simulate("\nYou still have to kill 1 * A kicking patient (A FAKE-private room)\n")
2496 Simulate("You still have to kill 1 * A snoring patient (Canyon Memorial Hospital-FAKE)\n")
2497 Simulate("You still have to kill 1 * An abominable snowman (The Snowy Path)\n")
2498 Simulate("You still have to kill 1 * The senior assassin (Assassins' Scrying Chamber)\n")
2499 Simulate("You still have to kill 1 * Bjorn (Realm of the Firebird)\n")
2500 Simulate("You still have to kill 2 * a crow (Realm of the Firebird)\n")
2501 Simulate("You still have to kill 2 * a gate guard (Realm of the Firebird)\n")
2502 Simulate("You still have to kill 1 * Destroyer of Minds (Deathtrap Dungeon)\n")
2503 Simulate("You still have to kill 1 * a tester of fire (The experimenting room (Fire))\n")
2504 Simulate("You still have to kill 1 * the third little pig (Pig Pen)\n")
2505 Simulate("You still have to kill 1 * The emperor's counselor (Faerie Tales II)\n\n")
2506 test_toggle = 0
2507
2508 end
2509 end
2510
2511 function qq_report (name, line, wildcards)
2512
2513 if (wildcards.channel ~= "") then
2514
2515 local output = ""
2516 local last_mob = ""
2517 local index = 0
2518
2519 for key, value in ipairs(gqList) do
2520 if (last_mob ~= gqList[key].mob) then
2521 index = index + 1
2522 if (gqList[key].type == "area") then
2523 output = string.format("%s %s) %s - %s, ", output, index, gqList[key].mob, gqList[key].areaName)
2524 else
2525 output = string.format("%s %s) %s - %s (%s), ", output, index, gqList[key].mob, gqList[key].roomName, gqList[key].areaId)
2526 end
2527 end
2528
2529 last_mob = gqList[key].mob
2530 end
2531
2532 if (output ~= "") then
2533 SendNoEcho( wildcards.channel .. " " .. output)
2534 end
2535 end
2536 end
2537
2538 function set_gq_refresh(name, line, wildcards)
2539 Note("set " .. USER_gq_mob_dead_refresh)
2540 if (USER_gq_mob_dead_refresh == "true") then
2541 USER_gq_mob_dead_refresh = "false"
2542 else
2543 USER_gq_mob_dead_refresh = "true"
2544 end
2545
2546 SetVariable("GQMobDeadRefresh", USER_gq_mob_dead_refresh)
2547
2548 init_triggers()
2549
2550 --ColourNote ("darkorange", "", "GQ Mob Dead Refresh : " .. USER_gq_mob_dead_refresh)
2551
2552 end
2553
2554 function OnPluginSaveState()
2555 SetVariable("GQMobDeadRefresh", USER_gq_mob_dead_refresh)
2556 end
2557
2558
2559 ------ Execute in Area ------
2560
2561 local execute_in_area_array = {}
2562
2563 function execute_in_area(id, areaId, functionPointer)
2564
2565 execute_in_area_array[id] = {
2566 areaId = areaId,
2567 func = functionPointer,
2568 index = 0,
2569 active = true,
2570 lastState = 3, -- standing
2571 standIndex = 0 -- count of stands in a row
2572 }
2573 --tprint(execute_in_area_array)
2574 EnableTimer("execute_in_area_timer", true)
2575
2576 end
2577
2578 function execute_in_area_tick(name, line, wildcards)
2579
2580 local localRoom = currentRoom
2581 local localState
2582
2583
2584 -- thread safety
2585 if (localRoom == nil) then
2586 DebugNote("Unknown Room")
2587 return
2588 end
2589
2590 if (char_status == nill) then
2591 DebugNote("Unknown char status")
2592 return
2593 else
2594 localState = tonumber(char_status.state)
2595 end
2596
2597 local isActive = false
2598
2599 --tprint(execute_in_area_array)
2600
2601 for index, value in pairs(execute_in_area_array) do
2602
2603 DebugNote("loop - " .. index)
2604 if (value.active == true) then
2605
2606 value.index = value.index + 1
2607
2608 if (value.index > 100) then
2609 value.active = false
2610 print("** aborting quickwhere timer for " .. index .. ", took too long to get to destination")
2611
2612 else
2613
2614 DebugNote("state:" .. localState .. ",:" .. value.areaId .. "==" .. localRoom.areaid)
2615
2616 if ((localState == 3 and value.lastState == 3)
2617 and value.areaId == localRoom.areaid) then
2618
2619 -- skip first timer tick
2620 value.index = value.index + 1
2621 value.standIndex = value.standIndex + 1
2622 if (value.standIndex < 2) then
2623 DebugNote("skip - index:" .. value.index)
2624 else
2625 DebugNote("executing - index:" .. value.index)
2626 value.func()
2627 value.active = false
2628 end
2629 else
2630 -- still moving.. reset index
2631 value.standIndex = 0
2632 end
2633 end
2634 end
2635
2636 value.lastState = localState
2637
2638 if (value.active == true) then
2639 isActive = true
2640 end
2641
2642 end
2643
2644 -- no timer items active.. disable
2645 if (isActive == false) then
2646 DebugNote("disable timer")
2647 EnableTimer("execute_in_area_timer", false)
2648 end
2649 end
2650
2651 -- v4
2652
2653 function gq_refresh(name, line, args)
2654 Execute("gq p")
2655 Execute("qq")
2656 end
2657
2658 ----------- EXTERNAL CALLOUTS -----------------------------
2659
2660 function remote_guess_mob_name(mobName, areaId, broadcast)
2661
2662 DebugNote("remote_guess_mob_name call:" .. mobName .. ":" .. areaId)
2663
2664 local rc, mobGuess, subMob = CallPlugin(
2665 search_destroy_id,
2666 "IGuessMobNameBroadcast",
2667 mobName,
2668 areaId)
2669
2670 if (subMob ~= nil) then
2671 DebugNote(subMob)
2672 end
2673
2674 DebugNote("remote_guess_mob_name return:" .. mobGuess)
2675 return mobGuess
2676
2677 end
2678
2679
2680 ------ Utils ------
2681
2682 function padRight(text, length, padChar)
2683 local padding = length - string.len(text)
2684 for i = 1, padding do
2685 text = text .. padChar
2686 end
2687 return text
2688 end
2689
2690 function sanitize_filename(str)
2691 str = string.gsub(str, "[^%w%s()_-]", "")
2692 return str
2693 end
2694
2695 function quote(str)
2696 return "\""..str.."\""
2697 end
2698
2699 function dbcheck(code)
2700
2701 if code ~= sqlite3.OK and -- no error
2702 code ~= sqlite3.ROW and -- completed OK with another row of data
2703 code ~= sqlite3.DONE then -- completed OK, no more rows
2704 local err = db:errmsg () -- the rollback will change the error message
2705 db:exec("ROLLBACK") -- rollback any transaction to unlock the database
2706 error (err, 2) -- show error in caller's context
2707 end -- if
2708
2709 end -- dbcheck
2710
2711 function fixsql(s)
2712
2713 if s then
2714 return "'" .. (string.gsub (s, "'", "''")) .. "'" -- replace single quotes with two lots of single quotes
2715 else
2716 return "NULL"
2717 end -- if
2718 end -- fixsql
2719
2720 function fixbool(b)
2721 if b then
2722 return 1
2723 else
2724 return 0
2725 end -- if
2726 end -- fixbool
2727
2728 function split(line, delim)
2729
2730 local result = {}
2731 local index = 1
2732
2733 for token in string.gmatch(line, delim) do
2734 result[index] = token
2735 index = index + 1
2736 end
2737
2738 return result
2739 end
2740
2741 function set_check_vidblain(name, line, wildcards)
2742
2743 if (USER_check_vidblain == "true") then
2744 USER_check_vidblain = "false"
2745 else
2746 USER_check_vidblain = "true"
2747 end
2748
2749 local msg = "off"
2750 if (USER_check_vidblain == "true") then
2751 msg = "on"
2752 end
2753 ColourNote ("darkorange", "", "No-portal vidblain assistance: " .. msg)
2754 end
2755
2756 function OnPluginSaveState()
2757
2758 SetVariable("XRunToCheckVidblain", USER_check_vidblain)
2759
2760 end
2761
2762 --------- Sql Execution ------------
2763
2764 function RunSql(name, line, wildcards)
2765
2766 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
2767 local db = assert(sqlite3.open(worldPath .. ".db"))
2768
2769 local index = 0
2770 local sql = wildcards.sql
2771 ColourNote("darkorange", "", "running :" .. sql)
2772 for row in db:nrows(sql) do
2773 index = index + 1
2774 print("----------- record " .. index .. " -----------" )
2775 tprint(row)
2776 -- print (serialize.save ("row", row))
2777 end
2778
2779 db:close_vm()
2780 end
2781
2782 function ExecSql (name, line, wildcards)
2783 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
2784 local db = assert(sqlite3.open(worldPath .. ".db"))
2785
2786 Note("executing " .. wildcards.sql)
2787 -- dbcheck (db:execute (fixsql(wildcards.sql)))
2788 db:execute(fixsql(wildcards.sql))
2789
2790 db:close_vm()
2791 Note("ok")
2792 end
2793
2794 -------------- DEBUG --------------------
2795
2796 function ext_debug(name, line, wildcards)
2797 if (showDebug == 0) then
2798 showDebug = 1
2799 else
2800 showDebug = 0
2801 end
2802 Note("Ext debug:" .. showDebug)
2803 end
2804
2805 function DebugNote(text)
2806 if (showDebug == 1) then
2807 Note("Extender ~ " .. text)
2808 end
2809 end
2810
2811 function DebugTPrint(title, obj)
2812 if (showDebug == 1) then
2813 DebugNote(title .. " : " .. serialize.save_simple(obj))
2814 end
2815 end
2816
2817 -------------- INSTALL MESSAGE ------------------
2818
2819 function InstallMessage()
2820 ColourNote("MediumSeaGreen", "", "+=======================================================+")
2821 ColourNote("MediumSeaGreen", "", "+ Extender Installed - type 'extender help' for options +")
2822 ColourNote("MediumSeaGreen", "", "+=======================================================+")
2823 end
2824
2825 InstallMessage()
2826
2827-------------- SORTING ------------------
2828
2829 function sort_cp_list(a,b)
2830 -- order by sortId, dupe, name,count
2831 -- '>' is descending and '<' is ascending
2832
2833 -- Note(a.sortId .. " " .. a.origMob .. " " .. a.bast_kills .. " " .. b.origMob)
2834 return (a.sortId > b.sortId)
2835 or (a.sortId == b.sortId and a.is_multi_area < b.is_multi_area)
2836 or (a.sortId == b.sortId and a.is_multi_area== b.is_multi_area and a.origMob > b.origMob)
2837 or (a.sortId == b.sortId and a.is_multi_area== b.is_multi_area and a.origMob == b.origMob and a.bast_kills > b.bast_kills)
2838 -- e.g,table.sort(tablename, sort_cp_list)
2839 end
2840 -- sort_cp_list2 is trash and for testing
2841 --[[
2842 function sort_cp_list2(a,b)
2843 -- order by sortId, dupe, name,count
2844 -- '>' is descending and '<' is ascending
2845 return (tostring(a.sortId) > tostring(b.sortId))
2846 or (tostring(a.sortId) == tostring(b.sortId) and a.is_multi_area < b.is_multi_area)
2847 or (tostring(a.sortId) == tostring(b.sortId) and a.is_multi_area== b.is_multi_area and a.origMob > b.origMob)
2848 or (tostring(a.sortId) == tostring(b.sortId) and a.is_multi_area== b.is_multi_area and a.origMob == b.origMob and a.bast_kills > b.bast_kills)
2849 -- e.g,table.sort(tablename, sort_cp_list)
2850 end
2851 ]]
2852 function sort_cp_list2(a,b)
2853 -- '>' is descending and '<' is ascending
2854 -- this big ass sort will take forever but it only fires once per cp
2855 return (a.sortId > b.sortId)
2856 or (a.sortId == b.sortId and a.is_multi_area < b.is_multi_area)
2857 or (a.sortId == b.sortId and a.is_multi_area == b.is_multi_area and a.origMob > b.origMob)
2858 or (a.sortId == b.sortId and a.is_multi_area == b.is_multi_area and a.origMob == b.origMob and a.type < b.type)
2859 or (a.sortId == b.sortId and a.is_multi_area == b.is_multi_area and a.origMob == b.origMob and a.type == b.type and a.bast_kills > b.bast_kills)
2860 -- e.g,table.sort(tablename, sort_cp_list)
2861 end
2862 function sort_distance(a,b)
2863 -- '>' is descending and '<' is ascending
2864 return (a.distance > b.distance)
2865 -- e.g,table.sort(tablename, sort_distance)
2866 end
2867 function sort1_func(a,b)
2868 -- sorts table on one column
2869 return tonumber(a.mrank) > tonumber(b.mrank)
2870 -- e.g,table.sort(tablename, sort1_func)
2871 end
2872
2873 function sort2_func(a, b)
2874 -- sorts two columns
2875 -- e.g., table.sort(tablename, sort2_func)
2876 return (a.name < b.name) or (a.name == b.name and tonumber(a.bast_kills) > tonumber(b.bast_kills))
2877 end
2878 function sort3_func(a, b)
2879 -- sorts two columns
2880 -- e.g., table.sort(tablename, sort3_func)
2881 return (a.area > b.area) or (a.area == b.area and tonumber(a.bast_kills) > tonumber(b.bast_kills))
2882 or (a.area == b.area and tonumber(a.bast_kills) == tonumber(b.bast_kills) and a.name > b.name)
2883 end
2884
2885 function mob_count(mob,area,room)
2886 local mob_count = 0
2887 local known_room = -1
2888
2889 if has_bast ~= 1 then
2890 --ColourNote("darkorange", "", " Bast Stat Monitor and Broadcast Plugins AKA stats.db not installed.")
2891 return mob_count, known_room
2892 end
2893 local sql = ""
2894
2895 --local sql_bast = [[where mk.name like '%]] .. (string.gsub (mob, "'", "''")) .. [[%']]
2896
2897 -- exact match for count
2898 --local sql_bast = [[where lower(mk.name) = ]] .. fixsql(mob)
2899 -- like match for count Michael's change on 10/31/19
2900 local sql_bast = [[where mk.name like "%]] .. mob .. [[%"]]
2901 if area ~= "" then
2902 --sql_bast = sql_bast .. " and " .. [[r.area = "]] .. area .. [["]]
2903 sql_bast = sql_bast .. " and " .. [[mk.area = "]] .. area .. [["]]
2904 end
2905 if room ~= "" then
2906 --sql_bast = sql_bast .. " and " .. [[r.uid = "]] .. room .. [["]]
2907 sql_bast = sql_bast .. " and " .. [[mk.room_id = "]] .. room .. [["]]
2908 end
2909
2910 sql_bast = [[select count(*) as kills, count(distinct mk.room_id) as rooms, max(mk.room_id) as max_rm_id
2911 from mobkills mk ]] .. "\n" ..
2912 sql_bast
2913
2914
2915 --Note(sql_bast)
2916
2917 db_bast = assert(sqlite3.open(GetInfo(66).."\\logs\\stats.db"))
2918 for row in db_bast:nrows(sql_bast) do
2919 mob_count = row.kills
2920 if row.rooms == 1 then
2921 known_room = row.max_rm_id
2922 end
2923 end
2924
2925 db_bast:close()
2926
2927 return mob_count, known_room
2928 end
2929
2930
2931 function trim(str)
2932 -- from PiL2 20.4
2933 return (str:gsub("^%s*(.-)%s*$", "%1"))
2934 end
2935 function sort_distance(a,b)
2936 -- sorts table on one column
2937 return tonumber(a.distance) < tonumber(b.distance)
2938 -- e.g,table.sort(tablename, sort1_func)
2939 end
2940
2941 --------- Scan Highlight Mob ------------
2942 -- need scan tags turned on for this to work
2943
2944
2945function togglescan(name, line, wildcards)
2946 if name == 'scanon' then
2947 EnableTriggerGroup("scan",true)
2948 if onQuest or onGq or onCp then
2949 --print('turning on scan matching')
2950 --phelper:enabletriggroup('scan', true)
2951 EnableTriggerGroup("scan",true)
2952 end
2953 elseif name == 'scanoff' then
2954 --print('turning off scan matching')
2955 --phelper:enabletriggroup('scan', false)
2956 EnableTriggerGroup("scan",false)
2957 end
2958end
2959
2960function checkmob(name, line, wildcards, styles)
2961 DebugNote("checkmob")
2962 -- need to make sure scan tags are on
2963 local found = false
2964 local addTxt = ""
2965 local mob = wildcards[2]
2966 mob = mob:lower()
2967 mob = trim(mob)
2968
2969 local color = "turquoise"
2970
2971 if not found and onQuest then
2972 if mob == questMob:lower() then
2973 found = 'quest'
2974 color = "red"
2975 addTxt = "[QUEST]"
2976 end
2977 end
2978
2979 if not found and onGq then
2980 for i,v in ipairs(gqList) do
2981 if mob == v.mob:lower() then
2982 found = 'gq'
2983 color = "turquoise"
2984 addTxt = "[GQ]"
2985 end
2986
2987 end
2988
2989 end
2990
2991 if not found and onCp then
2992 for i,v in ipairs(cpList) do
2993 if mob == v.mob:lower() then
2994 found = 'cp'
2995 color = "magenta"
2996 addTxt = "[CP]"
2997 end
2998 end
2999 end
3000
3001 if found then
3002 -- local textcolour = RGBColourToName(phelper[tostring(found) .. 'textcolour'])
3003 -- local backcolour = RGBColourToName(phelper[tostring(found) .. 'backcolour'])
3004
3005 for i,v in ipairs(styles) do
3006 ColourTell("black", color, v.text)
3007 end
3008 ColourTell("black", color, " " .. addTxt)
3009 -- ColourTell(textcolour, backcolour, ' - (' .. tostring(found):upper() .. ')')
3010 else
3011 for i,v in ipairs(styles) do
3012 ColourTell(RGBColourToName(v.textcolour), v.backcolour, v.text)
3013 end
3014 end
3015 ColourNote("", "", "")
3016end
3017
3018
3019
3020function OnPluginDisable ()
3021 -- SendNoEcho('tags scan off')
3022
3023
3024end -- OnPluginDisable
3025
3026
3027
3028]]>
3029</script>
3030
3031</muclient>
3032
3033
3034<!-- BUGS
3035
3036
3037-->