· 6 years ago · Nov 01, 2019, 05:04 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 search_rooms(wildcards.loc, 'area', wildcards.mob)
1905 end
1906
1907 function map_area_all(name, line, wildcards)
1908 search_rooms(wildcards.loc .. "|all", 'all', wildcards.mob)
1909 end
1910
1911 local search_rooms_sql =
1912 "SELECT r.uid as uid, r.name as name, info, r.area as area, " ..
1913 "ifnull(a.name, r.area) as area_name, 1 as DisplayOrder " ..
1914 "FROM rooms r " ..
1915 "LEFT OUTER JOIN areas a ON r.area = a.uid " ..
1916 "WHERE r.name = %s " ..
1917 "AND (%s = 'all' OR (a.name = %s OR r.area = %s)) " ..
1918
1919 "UNION " ..
1920
1921 "SELECT r.uid, r.name, info, r.area, " ..
1922 "ifnull(a.name, r.area) as area_name, 0 as DisplayOrder " ..
1923 "FROM rooms r " ..
1924 "LEFT OUTER JOIN areas a ON r.area = a.uid " ..
1925 "WHERE r.name <> %s " ..
1926 "AND r.name LIKE %s " ..
1927 "AND (%s = 'all' OR (a.name = %s OR r.area = %s)) " ..
1928 "ORDER BY Area, DisplayOrder DESC "
1929
1930 function search_rooms(room, searchType, fullMobName)
1931
1932 DebugNote("search_rooms(" .. room .."," .. searchType .. "," .. fullMobName .. ")")
1933
1934 if (room == nil or room == "") then
1935 Note("map_area() error : room is not known")
1936 return
1937 end
1938
1939 -- room|area
1940 local parts = split(room, "[^|]+") -- pipe delimited
1941 local room = parts[1]
1942 local area_id
1943 if (#parts == 2) then
1944 area_id = parts[2]
1945 else
1946 if (currentRoom ~= nil) then
1947 area_id = currentRoom.areaid
1948 else
1949 ColourNote("darkorange", "", "Area not known, falling back to mapper list")
1950 Execute("mapper list " .. parts[1])
1951 end
1952 end
1953
1954 if (room == nil) then
1955 Note("map_area() - Room not known")
1956 return
1957 end
1958 -- use this stmt if you want to return rooms with similar names
1959
1960 --like = "%"..room.."%"
1961 -- use this to return exact match of room name
1962 like = room
1963
1964 -- i forget what this does? Strip out a leading " ?
1965 --if string.sub(room,1,1) == "\"" and string.sub(room,-1) == "\"" then
1966 -- like = string.sub(room,2,-2)
1967 --end
1968
1969 local select = string.format(search_rooms_sql,
1970 fixsql(room),
1971 fixsql(area_id),
1972 fixsql(area_id),
1973 fixsql(area_id),
1974 fixsql(room),
1975 fixsql(like),
1976 fixsql(area_id),
1977 fixsql(area_id),
1978 fixsql(area_id))
1979 DebugNote(select)
1980
1981 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
1982 local db = assert(sqlite3.open(worldPath .. ".db"))
1983
1984 local results = {}
1985 local roomid_list = {}
1986
1987 for row in db:nrows(select) do
1988 -- sanitize text room ids for "unmappable" rooms that are now being mapped
1989 local id = (tonumber(row.uid) or -1)
1990 -- make safe against bad dbs
1991 local areaid_lookup = row.area or row.area_name
1992 local full_mobName = string.lower(fullMobName)
1993
1994 local bast_kills = mob_count(full_mobName,areaid_lookup,id)
1995 --Note(fullMobName .. " " .. areaid_lookup .. " " .. id)
1996 results[#results + 1] = {
1997 uid = id,
1998 name = row.name,
1999 info = row.info,
2000 area = row.area_name,
2001 areaid = areaid_lookup,
2002 mob = fullMobName,
2003 bast_kills = bast_kills
2004
2005 }
2006 -- make a list of room ids zhal this goes nowhere
2007 if (id > 0) then
2008 roomid_list[#roomid_list + 1] = id
2009 end
2010
2011 end -- finding rooms
2012 db:close_vm()
2013
2014
2015 local mob_mapping = {}
2016
2017 local freq_total = mob_mapping[-1] or 0
2018 DebugNote("freq_total:" .. freq_total)
2019
2020 -- add mob to room mapping
2021 for key, value in ipairs(results) do
2022
2023 local freq = mob_mapping[value.uid]
2024 if (freq ~= nil) then
2025 value.freq = math.floor((freq / freq_total) * 100)
2026 else
2027 value.freq = 0
2028 end
2029 end
2030
2031 table.sort(results, sort3_func)
2032
2033 print_rooms(results)
2034 end
2035
2036 function IPRINT_ROOMS(json)
2037 -- load serialize.save_simple data
2038 luastmt = "gPrintRooms = " .. json
2039 assert (loadstring (luastmt or "")) ()
2040
2041 print_rooms(gPrintRooms)
2042 end
2043
2044 -- uses results{ areaid, area, info, name, uid, freq }
2045 function print_rooms(results)
2046 -- print results
2047 gotoList = {}
2048 mapper_area_index = 0
2049 local last_area = ""
2050
2051 DebugTPrint("results", results)
2052
2053 if (USER_show_help == "true") then
2054 ColourNote("Gray", "", "Type 'go <Index>' or click link, to go to that room")
2055 ColourNote("Gray", "", " Index Room Name (uid)")
2056 ColourNote("Gray", "", "-------------------------------------------------")
2057 end
2058
2059 for key, value in ipairs(results) do
2060 DebugNote("area: " .. value.areaid )
2061 --Note("gmcp vs script " .. tostring(currentRoom.roomid) .. " vs " .. tostring(value.uid))
2062 -- create colors
2063 -- this is default, which is when you are in the same room
2064 local cBackground,cIndex,cRoomName,cRoomId,cBast,cDirections = "whitesmoke", "black", "black", "black", "black", "black"
2065 if tostring(currentRoom.roomid) ~= tostring(value.uid) then
2066 -- you are not in the same room
2067 cBackground = "black"
2068 cIndex = "white"
2069 cRoomName = "white"
2070 cRoomId = "yellow"
2071 cBast = "white"
2072 cDirections = "white"
2073 end
2074
2075 if (last_area ~= value.areaid) then
2076 -- michael
2077 local min = (area_range[value.area_name] or {min = 0}).min
2078 local max = (area_range[value.area_name] or {max = 300}).max
2079 local min_max = "[" .. min .. "-" .. max .. "]"
2080
2081 if (mapper_area_index == 0) then
2082 -- first line
2083 -- mapper_area_index <-- idk why bast had thi in the next line
2084 local areaLine = string.format(" %s %s",min_max, value.areaid)
2085 -- header that shows above hunt trick. No need to change color, used to be silver
2086 Hyperlink("go " .. mapper_area_index, areaLine, "go to area (go) " .. value.areaid, "darkorange", "black", 0)
2087 gotoList[mapper_area_index] = value.areaid
2088 mapper_area_index = mapper_area_index + 1
2089 else
2090 Note("")
2091 -- when multiple areas appear, e.g., search all database and multiple areas appear (xmall blah)
2092 -- could make this brighter and maybe even add lvl range
2093 -- area_range.mine and max
2094 --local areaLine = string.format("~~ %s", value.areaid)
2095 local areaLine = string.format(" %s %s",min_max, value.areaid)
2096 Hyperlink("xrt " .. value.areaid, areaLine, "go to area (xrt) " .. value.areaid, "darkorange", "black", 0)
2097 end
2098 print("")
2099 last_area = value.areaid
2100 end
2101
2102 -- v3 --
2103 local isPK = string.find((value.info or ""), "pk") ~= nil
2104 local isPKText = " "
2105 DebugNote("isPK: " .. tostring(isPK))
2106 if (isPK == true and showPK == "true") then
2107 isPKText = "[PK] "
2108 end
2109
2110 -- this is the first thing on the left, the ~~ #
2111 local line1 = string.format("~~ %s ",
2112
2113 padRight(mapper_area_index, 3, " "))
2114
2115 Hyperlink("go " .. mapper_area_index, line1, "go to item ht " .. mapper_area_index, cIndex, cBackground, 0,true)
2116
2117 local line2 = string.format("%s (%s) %s",
2118 padRight(string.gsub(value.name, "@[a-zA-Z]", ""), 20, " "),
2119 value.uid,value.bast_kills)
2120
2121 -- showed as room results and Quick-Where
2122 -- v4 --
2123 -- color isn't changed
2124 local namePad = 25
2125 if isPK then
2126 Hyperlink("go " .. mapper_area_index, isPKText, "go to item (pk) " .. mapper_area_index, "red", cBackground, 0, true)
2127 namePad = 20
2128 end
2129--Note("michael")
2130 local noUnderline = true
2131 local line10 = padRight(string.gsub(value.name, "@[a-zA-Z]", ""), namePad, " ")
2132 local line11 = padRight(" (" .. value.uid .. ")", 2, " ")
2133 local bast = padRight(" Cnt: " .. tostring(value.bast_kills),1, " ")
2134
2135 -- room name
2136 Hyperlink("go " .. mapper_area_index, line10,"go to item line (line 2.2) " .. mapper_area_index,
2137 cRoomName, cBackground, 0, noUnderline)
2138
2139 -- room id #
2140 Hyperlink("go " .. mapper_area_index, line11 , "go to item line (line 2.2) " .. mapper_area_index,
2141 cRoomId, cBackground, 0, noUnderline)
2142
2143 if has_bast == 1 then
2144 -- count of bast kills
2145 Hyperlink("go " .. mapper_area_index, bast, "go to item line (line 2.2) " .. mapper_area_index,
2146 cBast, cBackground, 0,noUnderline)
2147 end
2148 -- original
2149 --Hyperlink("go " .. mapper_area_index, line2, "go to item line (line 2.2) " .. mapper_area_index, "lightblue", "black", 0,noUnderline)-
2150
2151 -- this is at the right of every line. shows speedwalk but doesnt go
2152 Hyperlink("mapper where " .. value.uid,
2153 string.format("%-3s"," {?}"),
2154 "click for speedwalk to this room",
2155 cDirections,
2156 cBackground,
2157 0, noUnderline)
2158 gotoList[mapper_area_index] = value.uid
2159
2160 -- show room notes
2161 DebugNote("get note : " .. value.uid)
2162 get_notes(nil, value.uid, true)
2163
2164 print("")
2165 --ColourTell("","","\n")
2166
2167 mapper_area_index = mapper_area_index + 1
2168 end
2169
2170
2171 if (mapper_area_index == 0) then
2172 ColourNote("darkorange", "", "No matching rooms found.")
2173 end
2174
2175 if (USER_show_help == "true") then
2176 ColourNote("Gray", "", "-------------------------------------------------")
2177 Note("")
2178 end
2179
2180 end
2181
2182 function map_purgeroom (name, line, wildcards)
2183 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
2184 local db = assert(sqlite3.open(worldPath .. ".db"))
2185
2186 Note(string.format ("delete from exits WHERE fromuid = %s;", fixsql(currentRoom.roomid)))
2187 dbcheck (db:execute (string.format ("delete from exits WHERE fromuid = %s;", fixsql(currentRoom.roomid))))
2188 Note(string.format ("delete from exits WHERE touid = %s;", fixsql(currentRoom.roomid)))
2189 dbcheck (db:execute (string.format ("delete from exits WHERE touid = %s;", fixsql(currentRoom.roomid))))
2190 Note(string.format ("delete from rooms_lookup WHERE uid = %s;", fixsql(currentRoom.roomid)))
2191 dbcheck (db:execute (string.format ("delete from rooms_lookup WHERE uid = %s;", fixsql(currentRoom.roomid))))
2192 Note(string.format ("delete from rooms WHERE uid = %s;", fixsql(currentRoom.roomid)))
2193 dbcheck (db:execute (string.format ("delete from rooms WHERE uid = %s;", fixsql(currentRoom.roomid))))
2194 db:close_vm()
2195
2196 ColourNote("darkorange", "", "Purged room (" .. currentRoom.roomid .. ") from the mapper database.")
2197 end
2198
2199 local cp_simulate_toggle = 0
2200 function cp_simulate(name, line, wildcards)
2201
2202 Simulate("\n")
2203
2204 if (cp_simulate_toggle == 0) then
2205 --Simulate("You still have to kill * a slinky sylph (A corner in the bull pen)\n")
2206 Simulate("You still have to kill * a reoging lotus eater (Land of the Lotus-Eaters)\n")
2207 Simulate("You still have to kill * a satyr (The Labyrinth)\n")
2208 --Simulate("You still have to kill * a A mad bird (On A Pinnacle)\n")
2209 -- swirl good one
2210 --Simulate("You still have to kill * a swirl of orange and purple (Fantasy Creek)\n")
2211 --Simulate("You still have to kill * a swirl of orange and purple (Fantasy Creek)\n")
2212 --Simulate("You still have to kill * a patient drow miner (The Amber Mine)\n")
2213 --Simulate("You still have to kill * a giant mosquito (Jungles of Verume)\n")
2214 -- Simulate("You still have to kill * a giant mosquito (Jungles of Verume)\n")
2215 Simulate("You still have to kill * the head necromancer (Necromancers' Guild)\n")
2216 --Simulate("You still have to kill * a transparent gardener (Garden)\n")
2217 --Simulate("You still have to kill * a burst of anger (Anger and Violence)\n")
2218 Simulate("You still have to kill * a centaur stallion (The Labyrinth)\n")
2219 --Simulate("You still have to kill * a field rat (Inside the Northeast Watchtower)\n")
2220 --Simulate("You still have to kill * a shambling mound (The Labyrinth)\n")
2221 Simulate("You still have to kill * a blo ball (Nearing The Top Of The Pathway)\n")
2222 --Simulate("You still have to kill * an adventurous spelunker (An Underground River)\n")
2223 --Simulate("You still have to kill * a chipmunk (The Labyrinth)\n")
2224 Simulate("You still have to kill * a tall peasant (At the bonfire)\n")
2225 Simulate("You still have to kill * Gunnlod (Gunnlod's Home)\n")
2226 --Simulate("You still have to kill * a repairs troll (Observation stands)\n")
2227 --Simulate("You still have to kill * Michael (Blue Roomee)\n")
2228 Simulate("You still have to kill * Prince Rich'Erd (Sho'aram, Castle in the Sand)\n")
2229 Simulate("You still have to kill * Doctor Cameroon " .. [["]] .. "Rusty" .. [["]] .. " Baboon (Canyon Memorial Hospital)\n")
2230 --Note("You still have to kill * Doctor Cameroon " .. [["]] .. "Rusty" .. [["]] .. " Baboon (Canyon Memorial Hospital)")
2231 cp_simulate_toggle = 1
2232 else
2233
2234 Simulate("You still have to kill * a burst of anger (Anger and Violence)\n")
2235 Simulate("You still have to kill * a shambling mound (The Labyrinth)\n")
2236 Simulate("You still have to kill * a swirl of orange and purple (Fantasy Creek)\n")
2237 Simulate("You still have to kill * a field rat (Inside the Northeast Watchtower)\n")
2238 Simulate("You still have to kill * a transparent gardener (Garden)\n")
2239 Simulate("You still have to kill * a slinky sylph (A corner in the bull pen)\n")
2240 Simulate("You still have to kill * a tall peasant (At the bonfire)\n")
2241 cp_simulate_toggle = 0
2242 end
2243 Simulate("Note: Dead means that the target is dead, not that you have killed it.\n")
2244 Simulate("\n")
2245 Simulate("You have 6 days, 23 hours and 56 minutes left to finish this campaign.\n")
2246 Simulate("\n")
2247
2248 end
2249 function cp_simulate1(name, line, wildcards)
2250
2251 Simulate("\n")
2252
2253 if (cp_simulate_toggle == 0) then
2254 --Simulate("You still have to kill * Isscheburqua (Insanitaria)\n")
2255 Simulate("You still have to kill * a satyr (The Labyrinth)\n")
2256 Simulate("You still have to kill * a rook citizen (Avian Kingdom)\n")
2257 Simulate("You still have to kill * Lea, the farmer's daughter (Farmyard)\n")
2258 Simulate("You still have to kill * a rook citizen (Nesting Home)\n")
2259 Simulate("You still have to kill * a demon school student (The School of Horror)\n")
2260 Simulate("You still have to kill * a hookle fish (Black Lagoon)\n")
2261 Simulate("You still have to kill * Harry (Unknown Tower - Dead)\n")
2262 Simulate("You still have to kill * a former court jester (The Labyrinth)\n")
2263 Simulate("You still have to kill * Parent (The Kitchen)\n")
2264 Simulate("You still have to kill * a wealth redistribution specialist (Empyrean, Streets of Downfall)\n")
2265 Simulate("You still have to kill * the reaching thorns (Eternal Autumn)\n")
2266 Simulate("You still have to kill * Redtooth (Mossflower Wood - Dead)\n")
2267 Simulate("You still have to kill * Castle Guard (Rebellion of the Nix)\n")
2268 Simulate("You still have to kill * Jules (The Amazon Nation)\n")
2269 Simulate("You still have to kill * an earth fiend (The Broken Halls of Horath)\n")
2270 Simulate("You still have to kill * the spirit of Bakarne (The Empire of Aiighialla)\n")
2271 Simulate("You still have to kill * Elfgar Sous-Fled (Some Place)\n")
2272 Simulate("You still have to kill * the heart of a sandstorm (Living Mines of Dak'Tai)\n")
2273 cp_simulate_toggle = 1
2274 else
2275 Simulate("You still have to kill * a former court jester (The Labyrinth)\n")
2276 Simulate("You still have to kill * the heart of a sandstorm (Buried in the Great Desert's unrelenting dunes)\n")
2277 Simulate("You still have to kill * Parent (The Kitchen)\n")
2278 Simulate("You still have to kill * a rhino seraph (A Corridor of Cinnamon and Silver)\n")
2279 Simulate("You still have to kill * A sprite prisoner (A cell)\n")
2280
2281 cp_simulate_toggle = 0
2282 end
2283 Simulate("Note: Dead means that the target is dead, not that you have killed it.\n")
2284 Simulate("\n")
2285 Simulate("You have 6 days, 23 hours and 56 minutes left to finish this campaign.\n")
2286 Simulate("\n")
2287
2288 end
2289 function cp_simulate2(name, line, wildcards)
2290
2291 Simulate("\n")
2292
2293 if (cp_simulate_toggle == 0) then
2294 Simulate("You still have to kill * a practicing demon (The Arena)\n")
2295 Simulate("You still have to kill * Savinga, prince of death (In the clouds)\n")
2296 Simulate("You still have to kill * the cell keeper (A Hallway of Cells)\n")
2297 Simulate("You still have to kill * the ghost (The Silver Volcano)\n")
2298 Simulate("You still have to kill * Gabried, archangel of fire (In the clouds)\n")
2299 Simulate("You still have to kill * a demon berserker (On the Floor of the Arena)\n")
2300 Simulate("You still have to kill * the storm spirit (Storm Ships of Lem-Dagor)\n")
2301 Simulate("You still have to kill * Valefor, prince od theft (The Flying Citadel)\n")
2302 Simulate("You still have to kill * a huge Wave runner sergeant (The Storm Cruiser, Tempest)\n")
2303 Simulate("You still have to kill * a giggling girl (Inside Pumice Library)\n")
2304 Simulate("You still have to kill * a demon soldier (In the Stands surrounding the Arena)\n")
2305 Simulate("You still have to kill * Trey, the Unforgiven (A Hidden Den)\n")
2306 Simulate("You still have to kill * Prince Rich'Erd (Sho'aram, Castle in the Sand)\n")
2307 Simulate("You still have to kill * Doctor Cameroon " .. [["]] .. "Rusty" .. [["]] .. " Baboon (Canyon Memorial Hospital)\n")
2308 cp_simulate_toggle = 1
2309 else
2310 Simulate("You still have to kill * a former court jester (The Labyrinth)\n")
2311 Simulate("You still have to kill * the heart of a sandstorm (Buried in the Great Desert's unrelenting dunes)\n")
2312 Simulate("You still have to kill * a barber (The Labyrinth)\n")
2313 Simulate("You still have to kill * Parent (The Kitchen)\n")
2314 Simulate("You still have to kill * a rhino seraph (A Corridor of Cinnamon and Silver)\n")
2315 Simulate("You still have to kill * A sprite prisoner (A cell)\n")
2316
2317 cp_simulate_toggle = 0
2318 end
2319 Simulate("Note: Dead means that the target is dead, not that you have killed it.\n")
2320 Simulate("\n")
2321 Simulate("You have 6 days, 23 hours and 56 minutes left to finish this campaign.\n")
2322 Simulate("\n")
2323
2324 end
2325 -------- Area level capture -------
2326
2327
2328 --Commander Barcett tells you ' Good luck in your campaign!''
2329
2330 function area_index_start_gag(name, line, wildcards)
2331 DebugNote("area_index_start_gag - " .. wildcards[1] .. ":" .. wildcards[2])
2332 if (wildcards[1] == "0" and wildcards[2] == "298") then
2333 EnableTrigger("trg_area_index_start", true)
2334 EnableTrigger("trg_area_index_line", false)
2335 EnableTrigger("trg_area_index_end", false)
2336 EnableTrigger("trg_area_index_gag1", true)
2337 EnableTrigger("trg_area_index_gag2", true)
2338 else -- not an area index command
2339 EnableTrigger("trg_area_index_start", false)
2340 EnableTrigger("trg_area_index_line", false)
2341 EnableTrigger("trg_area_index_end", false)
2342 EnableTrigger("trg_area_index_gag1", false)
2343 EnableTrigger("trg_area_index_gag2", false)
2344 end
2345 end
2346
2347 function area_index_start(name, line, wildcards)
2348 DebugNote("area_index_start")
2349 EnableTrigger("trg_area_index_start", false)
2350 EnableTrigger("trg_area_index_line", true)
2351 EnableTrigger("trg_area_index_end", true)
2352
2353 area_range = {}
2354
2355 ColourNote("DarkOrange", "", "*** Indexing area levels...")
2356 end
2357
2358 function area_index_line(name, line, wildcards)
2359 DebugNote("area_index_line")
2360
2361 area_range[Trim(wildcards.area)] = {
2362 area = Trim(wildcards.area),
2363 min = tonumber(Trim(wildcards.min)),
2364 max = tonumber(Trim(wildcards.max)),
2365 lock = tonumber(Trim(wildcards.lock)) or 0 }
2366 --tprint(area_range[wildcards.area])
2367
2368 end
2369
2370 function area_index_end(name, line, wildcards)
2371 DebugNote("area_index_end")
2372
2373 EnableTrigger("trg_area_index_start", false)
2374 EnableTrigger("trg_area_index_line", false)
2375 EnableTrigger("trg_area_index_end", false)
2376 EnableTrigger("trg_area_index_gag1", false)
2377 EnableTrigger("trg_area_index_gag2", false)
2378
2379 ColourNote("DarkOrange", "", "*** Area levels indexed!")
2380
2381 DoAfterSpecial(2, "xset resume page size", sendto.execute)
2382
2383 SetVariable("areas_serial", serialize.save( "areas_ser", area_range ))
2384 Execute("cp check")
2385 end
2386
2387 function clean_sql(val)
2388 val = string.gsub(val , "'", "''")
2389 return val
2390 end
2391 -------- GQ ---------
2392 -- v2 --
2393
2394 function capture_gq_line(name, line, args)
2395
2396 EnableTrigger("x_gq_line_end", true)
2397
2398 if (gqList == nil) then
2399 gqList = {}
2400 gqIndex = 1
2401 end
2402
2403 --gqIndex = get_rooms_areas(gqList, gqIndex, wildcards.where, wildcards.mob, wildcards.qty)
2404 get_rooms_areas(gqList, args.where, args.mob, args.qty, "","gq")
2405
2406 end
2407
2408 function capture_gq_line_finished(name, line, wildcards)
2409 DebugNote("capture_gq_line_finished")
2410 EnableTriggerGroup("x_gq", false)
2411
2412 gqList = {}
2413 onGq = false
2414 -- broadcast this data for other plugins to consume
2415 local ser = serialize.save_simple(gqList)
2416 --print(ser)
2417 BroadcastPlugin(667, ser)
2418 end
2419
2420 function capture_gq_line_end(name, line, wildcards)
2421
2422 DebugNote("capture_gq_line_end")
2423
2424 EnableTriggerGroup("x_gq", false)
2425 clean_list(gqList)
2426 --[[
2427 if #gqList > 0 and has_bast == 1 then
2428 table.sort(gqList, sort_cp_list)
2429 end
2430 ]]
2431 print_rooms_areas(gqList, "qq")
2432
2433 if #gqList == 0 then onGq = false end
2434 -- broadcast this data for other plugins to consume
2435 local ser = serialize.save_simple(gqList)
2436 --print(ser)
2437 BroadcastPlugin(667, ser)
2438 end
2439
2440 local test_toggle = 0
2441
2442 function gq_list (name, line, wildcards)
2443
2444 gqList = {}
2445 gqList_old = gqList
2446 gqIndex = 1
2447
2448 EnableTrigger("x_gq_line", true)
2449 onGq = true
2450 if has_bast then
2451 Execute("gq check")
2452 else
2453 Send("gq c")
2454 end
2455 end
2456
2457 function gq_list_simulate (name, line, wildcards)
2458
2459 gqList = {}
2460 gqIndex = 1
2461 onGq = true
2462 EnableTrigger("x_gq_line", true)
2463
2464 if (test_toggle == 0) then
2465 Simulate("\nYou still have to kill 1 * A kicking patient (A FAKE-private room)\n")
2466 Simulate("You still have to kill 1 * A snoring patient (Canyon Memorial Hospital)\n")
2467 Simulate("You still have to kill 1 * Sergeant Steel (The Armory)\n")
2468 Simulate("You still have to kill 1 * An abominable snowman (The Snowy Path)\n")
2469 Simulate("You still have to kill 1 * The senior assassin (Assassins' Scrying Chamber)\n")
2470 Simulate("You still have to kill 1 * Lord Kyron (The DarkLight)\n")
2471 Simulate("You still have to kill 1 * Buck (Imperial Nation)\n")
2472 Simulate("You still have to kill 1 * Bjorn (Realm of the Firebird)\n")
2473 Simulate("You still have to kill 2 * a crow (Realm of the Firebird)\n")
2474 Simulate("You still have to kill 2 * a gate guard (Realm of the Firebird)\n")
2475 Simulate("You still have to kill 1 * Destroyer of Minds (Deathtrap Dungeon)\n")
2476 Simulate("You still have to kill 1 * Rudolph (In the Air)\n")
2477 Simulate("You still have to kill 1 * a tester of fire (The experimenting room (Fire))\n")
2478 Simulate("You still have to kill 2 * a Bad Apple (Umari's Castle)\n")
2479 Simulate("You still have to kill 1 * the third little pig (Pig Pen)\n\n")
2480
2481 test_toggle = 1
2482 elseif (test_toggle == 1) then
2483 -- TODO add 1 room and others area test here
2484 Simulate("\nYou still have to kill 1 * A kicking patient (A FAKE-private room)\n")
2485 Simulate("You still have to kill 1 * A snoring patient (Canyon Memorial Hospital-FAKE)\n")
2486 Simulate("You still have to kill 1 * An abominable snowman (The Snowy Path)\n")
2487 Simulate("You still have to kill 1 * The senior assassin (Assassins' Scrying Chamber)\n")
2488 Simulate("You still have to kill 1 * Bjorn (Realm of the Firebird)\n")
2489 Simulate("You still have to kill 2 * a crow (Realm of the Firebird)\n")
2490 Simulate("You still have to kill 2 * a gate guard (Realm of the Firebird)\n")
2491 Simulate("You still have to kill 1 * Destroyer of Minds (Deathtrap Dungeon)\n")
2492 Simulate("You still have to kill 1 * a tester of fire (The experimenting room (Fire))\n")
2493 Simulate("You still have to kill 1 * the third little pig (Pig Pen)\n")
2494 Simulate("You still have to kill 1 * The emperor's counselor (Faerie Tales II)\n\n")
2495 test_toggle = 0
2496
2497 end
2498 end
2499
2500 function qq_report (name, line, wildcards)
2501
2502 if (wildcards.channel ~= "") then
2503
2504 local output = ""
2505 local last_mob = ""
2506 local index = 0
2507
2508 for key, value in ipairs(gqList) do
2509 if (last_mob ~= gqList[key].mob) then
2510 index = index + 1
2511 if (gqList[key].type == "area") then
2512 output = string.format("%s %s) %s - %s, ", output, index, gqList[key].mob, gqList[key].areaName)
2513 else
2514 output = string.format("%s %s) %s - %s (%s), ", output, index, gqList[key].mob, gqList[key].roomName, gqList[key].areaId)
2515 end
2516 end
2517
2518 last_mob = gqList[key].mob
2519 end
2520
2521 if (output ~= "") then
2522 SendNoEcho( wildcards.channel .. " " .. output)
2523 end
2524 end
2525 end
2526
2527 function set_gq_refresh(name, line, wildcards)
2528 Note("set " .. USER_gq_mob_dead_refresh)
2529 if (USER_gq_mob_dead_refresh == "true") then
2530 USER_gq_mob_dead_refresh = "false"
2531 else
2532 USER_gq_mob_dead_refresh = "true"
2533 end
2534
2535 SetVariable("GQMobDeadRefresh", USER_gq_mob_dead_refresh)
2536
2537 init_triggers()
2538
2539 --ColourNote ("darkorange", "", "GQ Mob Dead Refresh : " .. USER_gq_mob_dead_refresh)
2540
2541 end
2542
2543 function OnPluginSaveState()
2544 SetVariable("GQMobDeadRefresh", USER_gq_mob_dead_refresh)
2545 end
2546
2547
2548 ------ Execute in Area ------
2549
2550 local execute_in_area_array = {}
2551
2552 function execute_in_area(id, areaId, functionPointer)
2553
2554 execute_in_area_array[id] = {
2555 areaId = areaId,
2556 func = functionPointer,
2557 index = 0,
2558 active = true,
2559 lastState = 3, -- standing
2560 standIndex = 0 -- count of stands in a row
2561 }
2562 --tprint(execute_in_area_array)
2563 EnableTimer("execute_in_area_timer", true)
2564
2565 end
2566
2567 function execute_in_area_tick(name, line, wildcards)
2568
2569 local localRoom = currentRoom
2570 local localState
2571
2572
2573 -- thread safety
2574 if (localRoom == nil) then
2575 DebugNote("Unknown Room")
2576 return
2577 end
2578
2579 if (char_status == nill) then
2580 DebugNote("Unknown char status")
2581 return
2582 else
2583 localState = tonumber(char_status.state)
2584 end
2585
2586 local isActive = false
2587
2588 --tprint(execute_in_area_array)
2589
2590 for index, value in pairs(execute_in_area_array) do
2591
2592 DebugNote("loop - " .. index)
2593 if (value.active == true) then
2594
2595 value.index = value.index + 1
2596
2597 if (value.index > 100) then
2598 value.active = false
2599 print("** aborting quickwhere timer for " .. index .. ", took too long to get to destination")
2600
2601 else
2602
2603 DebugNote("state:" .. localState .. ",:" .. value.areaId .. "==" .. localRoom.areaid)
2604
2605 if ((localState == 3 and value.lastState == 3)
2606 and value.areaId == localRoom.areaid) then
2607
2608 -- skip first timer tick
2609 value.index = value.index + 1
2610 value.standIndex = value.standIndex + 1
2611 if (value.standIndex < 2) then
2612 DebugNote("skip - index:" .. value.index)
2613 else
2614 DebugNote("executing - index:" .. value.index)
2615 value.func()
2616 value.active = false
2617 end
2618 else
2619 -- still moving.. reset index
2620 value.standIndex = 0
2621 end
2622 end
2623 end
2624
2625 value.lastState = localState
2626
2627 if (value.active == true) then
2628 isActive = true
2629 end
2630
2631 end
2632
2633 -- no timer items active.. disable
2634 if (isActive == false) then
2635 DebugNote("disable timer")
2636 EnableTimer("execute_in_area_timer", false)
2637 end
2638 end
2639
2640 -- v4
2641
2642 function gq_refresh(name, line, args)
2643 Execute("gq p")
2644 Execute("qq")
2645 end
2646
2647 ----------- EXTERNAL CALLOUTS -----------------------------
2648
2649 function remote_guess_mob_name(mobName, areaId, broadcast)
2650
2651 DebugNote("remote_guess_mob_name call:" .. mobName .. ":" .. areaId)
2652
2653 local rc, mobGuess, subMob = CallPlugin(
2654 search_destroy_id,
2655 "IGuessMobNameBroadcast",
2656 mobName,
2657 areaId)
2658
2659 if (subMob ~= nil) then
2660 DebugNote(subMob)
2661 end
2662
2663 DebugNote("remote_guess_mob_name return:" .. mobGuess)
2664 return mobGuess
2665
2666 end
2667
2668
2669 ------ Utils ------
2670
2671 function padRight(text, length, padChar)
2672 local padding = length - string.len(text)
2673 for i = 1, padding do
2674 text = text .. padChar
2675 end
2676 return text
2677 end
2678
2679 function sanitize_filename(str)
2680 str = string.gsub(str, "[^%w%s()_-]", "")
2681 return str
2682 end
2683
2684 function quote(str)
2685 return "\""..str.."\""
2686 end
2687
2688 function dbcheck(code)
2689
2690 if code ~= sqlite3.OK and -- no error
2691 code ~= sqlite3.ROW and -- completed OK with another row of data
2692 code ~= sqlite3.DONE then -- completed OK, no more rows
2693 local err = db:errmsg () -- the rollback will change the error message
2694 db:exec("ROLLBACK") -- rollback any transaction to unlock the database
2695 error (err, 2) -- show error in caller's context
2696 end -- if
2697
2698 end -- dbcheck
2699
2700 function fixsql(s)
2701
2702 if s then
2703 return "'" .. (string.gsub (s, "'", "''")) .. "'" -- replace single quotes with two lots of single quotes
2704 else
2705 return "NULL"
2706 end -- if
2707 end -- fixsql
2708
2709 function fixbool(b)
2710 if b then
2711 return 1
2712 else
2713 return 0
2714 end -- if
2715 end -- fixbool
2716
2717 function split(line, delim)
2718
2719 local result = {}
2720 local index = 1
2721
2722 for token in string.gmatch(line, delim) do
2723 result[index] = token
2724 index = index + 1
2725 end
2726
2727 return result
2728 end
2729
2730 function set_check_vidblain(name, line, wildcards)
2731
2732 if (USER_check_vidblain == "true") then
2733 USER_check_vidblain = "false"
2734 else
2735 USER_check_vidblain = "true"
2736 end
2737
2738 local msg = "off"
2739 if (USER_check_vidblain == "true") then
2740 msg = "on"
2741 end
2742 ColourNote ("darkorange", "", "No-portal vidblain assistance: " .. msg)
2743 end
2744
2745 function OnPluginSaveState()
2746
2747 SetVariable("XRunToCheckVidblain", USER_check_vidblain)
2748
2749 end
2750
2751 --------- Sql Execution ------------
2752
2753 function RunSql(name, line, wildcards)
2754
2755 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
2756 local db = assert(sqlite3.open(worldPath .. ".db"))
2757
2758 local index = 0
2759 local sql = wildcards.sql
2760 ColourNote("darkorange", "", "running :" .. sql)
2761 for row in db:nrows(sql) do
2762 index = index + 1
2763 print("----------- record " .. index .. " -----------" )
2764 tprint(row)
2765 -- print (serialize.save ("row", row))
2766 end
2767
2768 db:close_vm()
2769 end
2770
2771 function ExecSql (name, line, wildcards)
2772 local worldPath = GetInfo(66)..Trim(sanitize_filename(WorldName()))
2773 local db = assert(sqlite3.open(worldPath .. ".db"))
2774
2775 Note("executing " .. wildcards.sql)
2776 -- dbcheck (db:execute (fixsql(wildcards.sql)))
2777 db:execute(fixsql(wildcards.sql))
2778
2779 db:close_vm()
2780 Note("ok")
2781 end
2782
2783 -------------- DEBUG --------------------
2784
2785 function ext_debug(name, line, wildcards)
2786 if (showDebug == 0) then
2787 showDebug = 1
2788 else
2789 showDebug = 0
2790 end
2791 Note("Ext debug:" .. showDebug)
2792 end
2793
2794 function DebugNote(text)
2795 if (showDebug == 1) then
2796 Note("Extender ~ " .. text)
2797 end
2798 end
2799
2800 function DebugTPrint(title, obj)
2801 if (showDebug == 1) then
2802 DebugNote(title .. " : " .. serialize.save_simple(obj))
2803 end
2804 end
2805
2806 -------------- INSTALL MESSAGE ------------------
2807
2808 function InstallMessage()
2809 ColourNote("MediumSeaGreen", "", "+=======================================================+")
2810 ColourNote("MediumSeaGreen", "", "+ Extender Installed - type 'extender help' for options +")
2811 ColourNote("MediumSeaGreen", "", "+=======================================================+")
2812 end
2813
2814 InstallMessage()
2815
2816-------------- SORTING ------------------
2817
2818 function sort_cp_list(a,b)
2819 -- order by sortId, dupe, name,count
2820 -- '>' is descending and '<' is ascending
2821
2822 -- Note(a.sortId .. " " .. a.origMob .. " " .. a.bast_kills .. " " .. b.origMob)
2823 return (a.sortId > b.sortId)
2824 or (a.sortId == b.sortId and a.is_multi_area < b.is_multi_area)
2825 or (a.sortId == b.sortId and a.is_multi_area== b.is_multi_area and a.origMob > b.origMob)
2826 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)
2827 -- e.g,table.sort(tablename, sort_cp_list)
2828 end
2829 -- sort_cp_list2 is trash and for testing
2830 --[[
2831 function sort_cp_list2(a,b)
2832 -- order by sortId, dupe, name,count
2833 -- '>' is descending and '<' is ascending
2834 return (tostring(a.sortId) > tostring(b.sortId))
2835 or (tostring(a.sortId) == tostring(b.sortId) and a.is_multi_area < b.is_multi_area)
2836 or (tostring(a.sortId) == tostring(b.sortId) and a.is_multi_area== b.is_multi_area and a.origMob > b.origMob)
2837 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)
2838 -- e.g,table.sort(tablename, sort_cp_list)
2839 end
2840 ]]
2841 function sort_cp_list2(a,b)
2842 -- '>' is descending and '<' is ascending
2843 -- this big ass sort will take forever but it only fires once per cp
2844 return (a.sortId > b.sortId)
2845 or (a.sortId == b.sortId and a.is_multi_area < b.is_multi_area)
2846 or (a.sortId == b.sortId and a.is_multi_area == b.is_multi_area and a.origMob > b.origMob)
2847 or (a.sortId == b.sortId and a.is_multi_area == b.is_multi_area and a.origMob == b.origMob and a.type < b.type)
2848 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)
2849 -- e.g,table.sort(tablename, sort_cp_list)
2850 end
2851 function sort_distance(a,b)
2852 -- '>' is descending and '<' is ascending
2853 return (a.distance > b.distance)
2854 -- e.g,table.sort(tablename, sort_distance)
2855 end
2856 function sort1_func(a,b)
2857 -- sorts table on one column
2858 return tonumber(a.mrank) > tonumber(b.mrank)
2859 -- e.g,table.sort(tablename, sort1_func)
2860 end
2861
2862 function sort2_func(a, b)
2863 -- sorts two columns
2864 -- e.g., table.sort(tablename, sort2_func)
2865 return (a.name < b.name) or (a.name == b.name and tonumber(a.bast_kills) > tonumber(b.bast_kills))
2866 end
2867 function sort3_func(a, b)
2868 -- sorts two columns
2869 -- e.g., table.sort(tablename, sort3_func)
2870 return (a.area > b.area) or (a.area == b.area and tonumber(a.bast_kills) > tonumber(b.bast_kills))
2871 or (a.area == b.area and tonumber(a.bast_kills) == tonumber(b.bast_kills) and a.name > b.name)
2872 end
2873
2874 function mob_count(mob,area,room)
2875 local mob_count = 0
2876 local known_room = -1
2877
2878 if has_bast ~= 1 then
2879 --ColourNote("darkorange", "", " Bast Stat Monitor and Broadcast Plugins AKA stats.db not installed.")
2880 return mob_count, known_room
2881 end
2882 local sql = ""
2883
2884 --local sql_bast = [[where mk.name like '%]] .. (string.gsub (mob, "'", "''")) .. [[%']]
2885
2886 -- exact match for count
2887 --local sql_bast = [[where lower(mk.name) = ]] .. fixsql(mob)
2888 -- like match for count Michael's change on 10/31/19
2889 local sql_bast = [[where mk.name like "%]] .. mob .. [[%"]]
2890 if area ~= "" then
2891 --sql_bast = sql_bast .. " and " .. [[r.area = "]] .. area .. [["]]
2892 sql_bast = sql_bast .. " and " .. [[mk.area = "]] .. area .. [["]]
2893 end
2894 if room ~= "" then
2895 --sql_bast = sql_bast .. " and " .. [[r.uid = "]] .. room .. [["]]
2896 sql_bast = sql_bast .. " and " .. [[mk.room_id = "]] .. room .. [["]]
2897 end
2898
2899 sql_bast = [[select count(*) as kills, count(distinct mk.room_id) as rooms, max(mk.room_id) as max_rm_id
2900 from mobkills mk ]] .. "\n" ..
2901 sql_bast
2902
2903
2904 --Note(sql_bast)
2905
2906 db_bast = assert(sqlite3.open(GetInfo(66).."\\logs\\stats.db"))
2907 for row in db_bast:nrows(sql_bast) do
2908 mob_count = row.kills
2909 if row.rooms == 1 then
2910 known_room = row.max_rm_id
2911 end
2912 end
2913
2914 db_bast:close()
2915
2916 return mob_count, known_room
2917 end
2918
2919
2920 function trim(str)
2921 -- from PiL2 20.4
2922 return (str:gsub("^%s*(.-)%s*$", "%1"))
2923 end
2924 function sort_distance(a,b)
2925 -- sorts table on one column
2926 return tonumber(a.distance) < tonumber(b.distance)
2927 -- e.g,table.sort(tablename, sort1_func)
2928 end
2929
2930 --------- Scan Highlight Mob ------------
2931 -- need scan tags turned on for this to work
2932
2933
2934function togglescan(name, line, wildcards)
2935 if name == 'scanon' then
2936 EnableTriggerGroup("scan",true)
2937 if onQuest or onGq or onCp then
2938 --print('turning on scan matching')
2939 --phelper:enabletriggroup('scan', true)
2940 EnableTriggerGroup("scan",true)
2941 end
2942 elseif name == 'scanoff' then
2943 --print('turning off scan matching')
2944 --phelper:enabletriggroup('scan', false)
2945 EnableTriggerGroup("scan",false)
2946 end
2947end
2948
2949function checkmob(name, line, wildcards, styles)
2950 DebugNote("checkmob")
2951 -- need to make sure scan tags are on
2952 local found = false
2953 local addTxt = ""
2954 local mob = wildcards[2]
2955 mob = mob:lower()
2956 mob = trim(mob)
2957
2958 local color = "turquoise"
2959
2960 if not found and onQuest then
2961 if mob == questMob:lower() then
2962 found = 'quest'
2963 color = "red"
2964 addTxt = "[QUEST]"
2965 end
2966 end
2967
2968 if not found and onGq then
2969 for i,v in ipairs(gqList) do
2970 if mob == v.mob:lower() then
2971 found = 'gq'
2972 color = "turquoise"
2973 addTxt = "[GQ]"
2974 end
2975
2976 end
2977
2978 end
2979
2980 if not found and onCp then
2981 for i,v in ipairs(cpList) do
2982 if mob == v.mob:lower() then
2983 found = 'cp'
2984 color = "magenta"
2985 addTxt = "[CP]"
2986 end
2987 end
2988 end
2989
2990 if found then
2991 -- local textcolour = RGBColourToName(phelper[tostring(found) .. 'textcolour'])
2992 -- local backcolour = RGBColourToName(phelper[tostring(found) .. 'backcolour'])
2993
2994 for i,v in ipairs(styles) do
2995 ColourTell("black", color, v.text)
2996 end
2997 ColourTell("black", color, " " .. addTxt)
2998 -- ColourTell(textcolour, backcolour, ' - (' .. tostring(found):upper() .. ')')
2999 else
3000 for i,v in ipairs(styles) do
3001 ColourTell(RGBColourToName(v.textcolour), v.backcolour, v.text)
3002 end
3003 end
3004 ColourNote("", "", "")
3005end
3006
3007
3008
3009function OnPluginDisable ()
3010 -- SendNoEcho('tags scan off')
3011
3012
3013end -- OnPluginDisable
3014
3015
3016
3017]]>
3018</script>
3019
3020</muclient>
3021
3022
3023<!-- BUGS
3024
3025
3026-->