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