· 8 years ago · May 27, 2018, 09:24 PM
1<?xml version="1.0" encoding="iso-8859-1"?>
2<!DOCTYPE muclient [
3 <!ENTITY show_vnums "true" >
4 <!ENTITY show_timing "false" >
5 <!ENTITY show_completed "false" >
6 <!ENTITY show_other_areas "true" >
7 <!ENTITY show_area_exits "false" >
8 <!ENTITY show_up_down "true" >
9 <!ENTITY speedwalk_prefix "" >
10 <!ENTITY verbose_mode "true" >
11]>
12
13<muclient>
14
15<plugin
16 name="MM_GMCP_Mapper_GMCP"
17 author="Nick Gammon, Ruthgul"
18 id="f973af093e715dece34dc25f"
19 language="Lua"
20 purpose="GMCP Mapper for Materia Magica"
21 save_state="y"
22 date_written="2012-02-03 20:26:09"
23 date_modified="2017-01-21 23:20:21"
24 requires="4.71"
25 version="1.0"
26 >
27
28<description trim="y">
29
30<![CDATA[
31
32.-----------------------.
33 | MM_GMCP_Mapper_GMCP |
34`-----------------------'
35
36Materia Magica GMCP mapper.
37Original plugin by Nick Gammon. (http://www.gammon.com.au/forum/?id=10667)
38Modified to work with GMCP by Ruthgul. (Please report bugs to Ruthgul.)
39
40
41** REQUIRES **
42
43- The file mm_mapper.lua must be placed in the MUSHclient/lua directory.
44- MUSHclient _must_ have write access to its folder.
45- MM_GMCP_Handler (plugin id="f67c4339ed0591a5b010d05b") must be installed and enabled.
46- Client setting: Game, Configure, Output > [x] Convert IAC EOR/GA to new line (must be checked).
47- Game settings: SHOW-EXITS must be ON (to show room numbers, road exits and unmapped exits).
48
49
50Notes:
51
52* The window can be dragged to a new location by dragging the room name.
53* Your current room is always in the center with a bolder border.
54* LH-click on a room to speed-walk to it. RH-click on a room for options.
55* LH-click on the "*" button on the bottom-left corner to configure it.
56
57
58Syntax:
59
60> Interface:
61
62* mapper zoom out - zoom out
63* mapper zoom in - zoom in
64
65* mapper hide - hide map
66* mapper show - show map
67
68* mapper color terrain [on|off] - toggle PK vs terrain coloring (off by default)
69* mapper show flags [on|off] - toggle showing room flags on/off (off by default)
70* mapper show numbers [on|off] - toggle showing/logging room numbers on/off (off by default)
71* mapper show road exits [on|off] - toggle showing on-road exits on/off (off by default)
72* mapper show unmapped exits [on|off] - toggle showing unmapped exits on/off (off by default)
73* mapper draw other floors [on|off] - toggle drawing other floors on/off (on by default)
74
75* mapper auto-open [on|off] - toggle auto-open doors on/off (on by default)
76* mapper safewalk [on|off] - toggle avoid PK rooms and DTs on/off (off by default, only works for mapper goto, not for clicking on a room in the map, not for mapper path)
77
78* mapper peek [<room#>] - redraw the map centered on any room, by its room number
79
80> Queries:
81
82* mapper where <room_name> - show room# and area for an existing room, by its room name (Note that the % symbol can be used as a wildcard.)
83* mapper find <text> - search by keywords (eg, courtyard OR lobby)
84* mapper bookmarks - show nearby rooms that you bookmarked ('nearby' is determined by your mapper's depth setting)
85* mapper findbm <text> - search by bookmark
86* mapper flags <flags> - search by room flags
87* mapper notflags <flags> - search by negated room flags
88* mapper adjacent <full_room_name> - show adjacent rooms with different names
89
90* mapper safes - show nearby safe rooms
91* mapper cpks - show nearby CPK rooms
92
93* mapper dts - show nearby death traps
94* mapper shops - show nearby shops
95* mapper trainers - show nearby trainers
96
97> Movement:
98
99* mapper path <room#> - show directions to a room, by its room number
100* mapper path <room1#> <room2#> - show directions from room1 to room2, by room number
101
102* mapper goto <room#> - walk to a room, by its room number (partial)
103* mapper stop - cancel any current speedwalk
104* mapper resume - resume last speedwalk or hyperlinked speedwalk
105* mapper speedwalk next - show (or SAPI say) next direction of the speedwalk (to flee, etc.)
106
107> Special areas:
108
109* mapper map wilds [on|off] - toggle mapping the wilds on/off (off by default)
110
111> Maintanence:
112
113* mapper purge area <full_area_name> - delete an entire area from the database
114* mapper purge wilds <full_plane_name> - deletes rooms in the vmap except for roads
115* mapper purge pursuer - delete changing orc pursuer maze info from the database
116* mapper purge sandbox - delete housing sandbox info from the database
117* mapper purge molehill - delete changing labyrinthine molehill info from the database
118
119* mapper maintenance - show a list of advanced maintenance & privacy aliases
120
121
122Authors: Nick Gammon, Ruthgul (maintained by Ruthgul)
123
124Latest version:
125http://github.com/mu3r73/mm-mushclient-scripts
126
127]]>
128
129</description>
130
131</plugin>
132
133
134
135<!-- Aliases -->
136
137<aliases>
138
139<!-- interface -->
140
141 <alias
142 enabled="y"
143 match="^mapper[ ]+reset[ ]+defaults$"
144 regexp="y"
145 sequence="100"
146 omit_from_command_history="y"
147 omit_from_output="y"
148 script="reset_defaults"
149 >
150 </alias>
151
152 <alias
153 enabled="y"
154 match="^mapper[ ]+show[ ]+database[ ]+mods(|[ ]+(?P<status>(on|off)))$"
155 regexp="y"
156 send_to="12"
157 sequence="100"
158 >
159 <send>toggle_show_database_mods_to("%<status>")
160</send>
161 </alias>
162
163 <alias
164 enabled="y"
165 match="^mapper[ ]+zoom[ ]+out$"
166 regexp="y"
167 sequence="100"
168 omit_from_command_history="y"
169 omit_from_output="y"
170 script="mapper.zoom_out"
171 >
172 </alias>
173
174 <alias
175 enabled="y"
176 match="^mapper[ ]+zoom[ ]+in$"
177 regexp="y"
178 sequence="100"
179 omit_from_command_history="y"
180 omit_from_output="y"
181 script="mapper.zoom_in"
182 >
183 </alias>
184
185 <alias
186 enabled="y"
187 match="^mapper[ ]+hide$"
188 regexp="y"
189 send_to="12"
190 sequence="100"
191 >
192 <send>mapper_hide(true)
193</send>
194 </alias>
195
196 <alias
197 enabled="y"
198 match="^mapper[ ]+show$"
199 regexp="y"
200 send_to="12"
201 sequence="100"
202 >
203 <send>mapper_show(true)
204</send>
205 </alias>
206
207 <alias
208 enabled="y"
209 match="^mapper[ ]+colo(|u)r[ ]+terrain(|[ ]+(?P<status>(on|off)))$"
210 regexp="y"
211 send_to="12"
212 sequence="100"
213 >
214 <send>toggle_terrain_to("%<status>")
215</send>
216 </alias>
217
218 <alias
219 enabled="y"
220 match="^mapper[ ]+show[ ]+flags(|[ ]+(?P<status>(on|off)))$"
221 regexp="y"
222 send_to="12"
223 sequence="100"
224 >
225 <send>toggle_vis_flags_to("%<status>")
226</send>
227 </alias>
228
229 <alias
230 enabled="y"
231 match="^mapper[ ]+show[ ]+numbers(|[ ]+(?P<status>(on|off)))$"
232 regexp="y"
233 send_to="12"
234 sequence="100"
235 >
236 <send>toggle_vis_number_to("%<status>")
237</send>
238 </alias>
239
240 <alias
241 enabled="y"
242 match="^mapper[ ]+show[ ]+road[ ]+exits(|[ ]+(?P<status>(on|off)))$"
243 regexp="y"
244 send_to="12"
245 sequence="100"
246 >
247 <send>toggle_vis_road_exits_to("%<status>")
248</send>
249 </alias>
250
251 <alias
252 enabled="y"
253 match="^mapper[ ]+show[ ]+unmapped[ ]+exits(|[ ]+(?P<status>(on|off)))$"
254 regexp="y"
255 send_to="12"
256 sequence="100"
257 >
258 <send>toggle_vis_unmapped_to("%<status>")
259</send>
260 </alias>
261
262 <alias
263 enabled="y"
264 match="^mapper[ ]+draw[ ]+other[ ]+floors(|[ ]+(?P<status>(on|off)))$"
265 regexp="y"
266 send_to="12"
267 sequence="100"
268 >
269 <send>toggle_draw_other_floors_to("%<status>")
270</send>
271 </alias>
272
273 <alias
274 enabled="y"
275 match="^mapper[ ]+auto\-open(|[ ]+(?P<status>(on|off)))$"
276 regexp="y"
277 send_to="12"
278 sequence="100"
279 >
280 <send>toggle_auto_open_to("%<status>")
281</send>
282 </alias>
283
284 <alias
285 enabled="y"
286 match="^mapper[ ]+safewalk(|[ ]+(?P<status>(on|off)))$"
287 regexp="y"
288 send_to="12"
289 sequence="100"
290 >
291 <send>toggle_safewalk_to("%<status>")
292</send>
293 </alias>
294
295 <alias
296 enabled="y"
297 match="^mapper[ ]+peek[ ]+(?P<id>[0-9]+)$"
298 regexp="y"
299 send_to="12"
300 sequence="100"
301 >
302 <send>peek_room("%<id>")
303</send>
304 </alias>
305
306
307<!-- queries -->
308
309 <alias
310 enabled="y"
311 match="^mapper[ ]+where[ ]+(?P<name>[^\:]+)$"
312 regexp="y"
313 send_to="12"
314 sequence="100"
315 >
316 <send>map_where("%<name>")
317</send>
318 </alias>
319
320 <alias
321 enabled="y"
322 match="^mapper[ ]+wheree[ ]+(?P<name>[^\:]+)(| a\:(?P<area>[^\:]+))$"
323 regexp="y"
324 send_to="12"
325 sequence="100"
326 >
327 <send>map_wheree("%<name>", "%<area>")
328</send>
329 </alias>
330
331 <alias
332 enabled="y"
333 match="^mapper[ ]+find[ ]+(?P<what>[a-zA-Z0-9 \,\.\'\-]+)$"
334 regexp="y"
335 send_to="12"
336 sequence="100"
337 >
338 <send>map_find("%<what>")
339</send>
340 </alias>
341
342 <alias
343 enabled="y"
344 match="^mapper[ ]+(bm|book(|mark(|s)))$"
345 regexp="y"
346 sequence="100"
347 script="map_bookmarks"
348 >
349 </alias>
350
351 <alias
352 enabled="y"
353 match="^mapper[ ]+findbm[ ]+(?P<bm>[a-zA-Z0-9 \,\.\'\-]+)$"
354 regexp="y"
355 send_to="12"
356 sequence="100"
357 >
358 <send>map_find_bookmark("%<bm>")
359</send>
360 </alias>
361
362 <alias
363 enabled="y"
364 match="^mapper[ ]+flags[ ]+(?P<flags>[a-z \-]+)$"
365 regexp="y"
366 send_to="12"
367 sequence="100"
368 >
369 <send>map_list_by_flags("%<flags>")
370</send>
371 </alias>
372
373 <alias
374 enabled="y"
375 match="^mapper[ ]+notflags[ ]+(?P<flags>[a-z \-]+)$"
376 regexp="y"
377 send_to="12"
378 sequence="100"
379 >
380 <send>map_list_by_not_flags("%<flags>")
381</send>
382 </alias>
383
384 <alias
385 enabled="y"
386 match="^mapper[ ]+adjacent[ ]+(?P<name>[^\:]+)$"
387 regexp="y"
388 send_to="12"
389 sequence="100"
390 >
391 <send>map_show_adjacent_rooms("%<name>")
392</send>
393 </alias>
394
395 <alias
396 enabled="y"
397 match="^mapper[ ]+safes$"
398 regexp="y"
399 sequence="100"
400 script="map_safe"
401 >
402 </alias>
403
404 <alias
405 enabled="y"
406 match="^mapper[ ]+cpks$"
407 regexp="y"
408 sequence="100"
409 script="map_cpk"
410 >
411 </alias>
412
413 <alias
414 enabled="y"
415 match="^mapper[ ]+dts$"
416 regexp="y"
417 sequence="100"
418 script="map_dts"
419 >
420 </alias>
421
422 <alias
423 enabled="y"
424 match="^mapper[ ]+shops$"
425 regexp="y"
426 sequence="100"
427 script="map_shops"
428 >
429 </alias>
430
431 <alias
432 enabled="y"
433 match="^mapper[ ]+trainers$"
434 regexp="y"
435 sequence="100"
436 script="map_trainers"
437 >
438 </alias>
439
440
441<!-- movement -->
442
443 <alias
444 enabled="y"
445 match="^mapper[ ]+path[ ]+(?P<id>[0-9]+)$"
446 regexp="y"
447 send_to="12"
448 sequence="100"
449 >
450 <send>map_path("%<id>")
451</send>
452 </alias>
453
454 <alias
455 enabled="y"
456 match="^mapper[ ]+path[ ]+(?P<id1>[0-9]+)[ ]+(?P<id2>[0-9]+)$"
457 regexp="y"
458 send_to="12"
459 sequence="100"
460 >
461 <send>map_path2("%<id1>", "%<id2>")
462</send>
463 </alias>
464
465 <alias
466 enabled="y"
467 match="^mapper[ ]+goto[ ]+(?P<id>[0-9]+)$"
468 regexp="y"
469 send_to="12"
470 sequence="100"
471 >
472 <send>map_goto("%<id>")
473</send>
474 </alias>
475
476 <alias
477 enabled="y"
478 match="^mapper[ ]+stop$"
479 regexp="y"
480 sequence="100"
481 script="mapper.cancel_speedwalk"
482 >
483 </alias>
484
485 <alias
486 enabled="y"
487 match="^mapper[ ]+resume$"
488 regexp="y"
489 sequence="100"
490 script="map_resume"
491 >
492 </alias>
493
494 <alias
495 enabled="y"
496 match="^mapper[ ]+speed(|walk)[ ]+next$"
497 regexp="y"
498 sequence="100"
499 script="map_speedwalk_next"
500 >
501 </alias>
502
503
504<!-- special areas -->
505
506 <alias
507 enabled="y"
508 match="^mapper[ ]+map[ ]+wilds(|[ ]+(?P<status>(on|off)))$"
509 regexp="y"
510 send_to="12"
511 sequence="100"
512 >
513 <send>toggle_wilds_mapping("%<status>")
514</send>
515 </alias>
516
517
518<!-- maintenance -->
519
520 <alias
521 enabled="y"
522 match="^mapper[ ]+purge[ ]+area[ ]+(?P<areaid>[a-zA-Z0-9 \,\.\'\-]+)$"
523 regexp="y"
524 send_to="12"
525 sequence="100"
526 >
527 <send>purge_entire_area("%<areaid>")
528</send>
529 </alias>
530
531 <alias
532 enabled="y"
533 match="^mapper[ ]+purge[ ]+wilds[ ]+(?P<planeid>[a-zA-Z ]+)$"
534 regexp="y"
535 send_to="12"
536 sequence="100"
537 >
538 <send>purge_wilds("%<planeid>")
539</send>
540 </alias>
541
542 <alias
543 enabled="y"
544 match="^mapper[ ]+purge[ ]+pursuer$"
545 regexp="y"
546 sequence="100"
547 script="purge_pursuer"
548 >
549 </alias>
550
551 <alias
552 enabled="y"
553 match="^mapper[ ]+purge[ ]+sandbox$"
554 regexp="y"
555 sequence="100"
556 script="purge_sandbox"
557 >
558 </alias>
559
560 <alias
561 enabled="y"
562 match="^mapper[ ]+purge[ ]+molehill$"
563 regexp="y"
564 sequence="100"
565 script="purge_molehill"
566 >
567 </alias>
568
569 <alias
570 enabled="y"
571 match="^mapper[ ]+maintenance$"
572 regexp="y"
573 sequence="100"
574 script="help_maintenance"
575 >
576 </alias>
577
578
579<!-- maintenance - queries -->
580
581 <alias
582 match="^mapper[ ]+roominfo(|[ ]+(?P<id>[0-9]+))$"
583 enabled="y"
584 regexp="y"
585 send_to="12"
586 sequence="100"
587 >
588 <send>show_room_info("%<id>")
589</send>
590 </alias>
591
592 <alias
593 match="^mapper[ ]+export[ ]+rooms[ ]+(?P<name>.+)$"
594 enabled="y"
595 regexp="y"
596 send_to="12"
597 sequence="100"
598 >
599 <send>export_rooms("%<name>")
600</send>
601 </alias>
602
603 <alias
604 match="^mapper[ ]+export[ ]+area[ ]+(?P<name>.+)$"
605 enabled="y"
606 regexp="y"
607 send_to="12"
608 sequence="100"
609 >
610 <send>export_area("%<name>")
611</send>
612 </alias>
613
614
615<!-- maintenance - additions -->
616
617 <alias
618 match="^mapper[ ]+addroom[ ]+(?P<id>[0-9]+)[ ]+n\:(?P<name>.+) a\:(?P<area>.+) f\:(?P<flags>.+) t\:(?P<terrain>.+) ti\:(?P<terraininfo>.+)$"
619 enabled="y"
620 regexp="y"
621 send_to="12"
622 sequence="100"
623 >
624 <send>map_add_room("%<id>", "%<name>", "%<area>", "%<flags>", "%<terrain>", "%<terraininfo>")
625</send>
626 </alias>
627
628 <alias
629 match="^mapper[ ]+addexit[ ]+(?P<dir>[a-z]+)(|[ ]+f\:(?P<fromid>[0-9]+)) t\:(?P<toid>[0-9]+)$"
630 enabled="y"
631 regexp="y"
632 send_to="12"
633 sequence="100"
634 >
635 <send>map_add_exit("%<dir>", "%<fromid>", "%<toid>")
636</send>
637 </alias>
638
639 <alias
640 match="^mapper[ ]+addbm(|[ ]+(?P<roomid>[0-9]+))(|[ ]+b\:(?P<book>.+))$"
641 enabled="y"
642 regexp="y"
643 send_to="12"
644 sequence="100"
645 >
646 <send>map_add_bookmark("%<roomid>", "%<book>")
647</send>
648 </alias>
649
650
651<!-- maintenance - deletions -->
652
653 <alias
654 match="^mapper[ ]+delroom[ ]+(?P<id>[0-9]+)$"
655 enabled="y"
656 regexp="y"
657 send_to="12"
658 sequence="100"
659 >
660 <send>map_del_room("%<id>")
661</send>
662 </alias>
663
664 <alias
665 match="^mapper[ ]+delexit[ ]+(?P<dir>[a-z]+)(|[ ]+f\:(?P<fromid>[0-9]+))$"
666 enabled="y"
667 regexp="y"
668 send_to="12"
669 sequence="100"
670 >
671 <send>map_del_exit("%<dir>", "%<fromid>")
672</send>
673 </alias>
674
675 <alias
676 match="^mapper[ ]+delexits[ ]+(?P<fromid>[0-9]+)$"
677 enabled="y"
678 regexp="y"
679 send_to="12"
680 sequence="100"
681 >
682 <send>map_del_exits("%<fromid>")
683</send>
684 </alias>
685
686 <alias
687 match="^mapper[ ]+delbm(|[ ]+(?P<roomid>[0-9]+))$"
688 regexp="y"
689 enabled="y"
690 send_to="12"
691 sequence="100"
692 >
693 <send>map_del_bookmark("%<roomid>")
694</send>
695 </alias>
696
697
698<!-- maintenance - tags -->
699
700 <alias
701 match="^mapper[ ]+dt(|[ ]+(?P<id>[0-9]+))$"
702 enabled="y"
703 regexp="y"
704 send_to="12"
705 sequence="100"
706 >
707 <send>map_toggle_tag("%<id>", "dt")
708</send>
709 </alias>
710
711 <alias
712 match="^mapper[ ]+trap(|[ ]+(?P<id>[0-9]+))$"
713 enabled="y"
714 regexp="y"
715 send_to="12"
716 sequence="100"
717 >
718 <send>map_toggle_tag("%<id>", "trap")
719</send>
720 </alias>
721
722 <alias
723 match="^mapper[ ]+no(|\-)speed(|[ ]+(?P<id>[0-9]+))$"
724 enabled="y"
725 regexp="y"
726 send_to="12"
727 sequence="100"
728 >
729 <send>map_toggle_tag("%<id>", "no-speed")
730</send>
731 </alias>
732
733 <alias
734 match="^mapper[ ]+shop(|[ ]+(?P<id>[0-9]+))$"
735 enabled="y"
736 regexp="y"
737 send_to="12"
738 sequence="100"
739 >
740 <send>map_toggle_tag("%<id>", "shop")
741</send>
742 </alias>
743
744 <alias
745 match="^mapper[ ]+train(|er)(|[ ]+(?P<id>[0-9]+))$"
746 enabled="y"
747 regexp="y"
748 send_to="12"
749 sequence="100"
750 >
751 <send>map_toggle_tag("%<id>", "trainer")
752</send>
753 </alias>
754
755
756<!-- maintenance - privacy -->
757
758 <alias
759 enabled="y"
760 match="^mapper[ ]+purge[ ]+clanhalls$"
761 regexp="y"
762 sequence="100"
763 script="purge_clanhalls"
764 >
765 </alias>
766
767 <alias
768 enabled="y"
769 match="^mapper[ ]+purge[ ]+homes$"
770 regexp="y"
771 sequence="100"
772 script="purge_player_homes"
773 >
774 </alias>
775
776 <alias
777 enabled="y"
778 match="^mapper[ ]+purge[ ]+bookmarks$"
779 regexp="y"
780 sequence="100"
781 script="purge_notes"
782 >
783 </alias>
784
785
786<!-- maintenance - rebuild data -->
787
788 <alias
789 enabled="y"
790 match="^mapper[ ]+(?P<cmd>(recreate|upgrade))[ ]+database$"
791 regexp="y"
792 send_to="12"
793 sequence="100"
794 >
795 <send>recreate_database("%<cmd>")
796</send>
797 </alias>
798
799 <alias
800 enabled="y"
801 match="^mapper[ ]+rebuild[ ]+lookup$"
802 regexp="y"
803 sequence="100"
804 script="rebuild_lookup"
805 >
806 </alias>
807
808
809<!-- used by scripts -->
810
811 <alias
812 enabled="y"
813 match="^tprt$"
814 regexp="y"
815 send_to="12"
816 sequence="100"
817 >
818 <send>notify_teleport()
819</send>
820 </alias>
821
822 <alias
823 enabled="y"
824 match="^prtl$"
825 regexp="y"
826 send_to="12"
827 sequence="100"
828 >
829 <send>notify_portal()
830</send>
831 </alias>
832
833 <alias
834 enabled="y"
835 match="^mapper[ ]+hyper[ ]+(?P<id>[0-9]+)$"
836 regexp="y"
837 send_to="12"
838 sequence="100"
839 >
840 <send>map_hyperlink("%<id>")
841</send>
842 </alias>
843
844
845<!-- Plugin help -->
846
847 <alias
848 enabled="y"
849 ignore_case="y"
850 match="^(|MM\_GMCP\_)Mapper(|\_GMCP)(|( |\:)help)$"
851 regexp="y"
852 script="OnHelp"
853 >
854 </alias>
855
856</aliases>
857
858
859
860<trigger
861enabled="y"
862keep_evaluating="y"
863match="^You open the (.*) (door|doors|gate|grating|trapdoor).*\.$"
864regexp="y"
865send_to="12"
866sequence="100"
867>
868<send>local dir = {}
869dir['northeast'] = 'ne'
870dir['northwest'] = 'nw'
871dir['southeast'] = 'se'
872dir['southwest'] = 'nw'
873if dir[%1] ~= nil then
874Execute(dir[%1])
875else
876Execute(string.sub("%1", 1, 1))
877end</send>
878</trigger>
879
880
881<!-- auto-open doors -->
882
883 <trigger
884 enabled="y"
885 keep_evaluating="y"
886 match="^(The (.+) (is|are) closed|A strange force blocks your passage)\.$"
887 regexp="y"
888 send_to="12"
889 sequence="100"
890 >
891 <send>mapper.auto_open()
892</send>
893 </trigger>
894
895 <trigger
896 enabled="y"
897 keep_evaluating="y"
898 match="^(.+)\: It\'s locked\.$"
899 regexp="y"
900 send_to="12"
901 sequence="100"
902 >
903 <send>mapper.stop_auto_open()
904</send>
905 </trigger>
906
907
908 <!-- various messages that cancel speedwalks -->
909
910 <trigger
911 enabled="y"
912 match="You are too exhausted. Better rest for a bit."
913 keep_evaluating="y"
914 regexp="y"
915 script="mapper.cancel_speedwalk"
916 sequence="100"
917 >
918 </trigger>
919
920
921
922
923
924<!-- Scripts -->
925
926<script>
927
928local show_vnums = &show_vnums;
929local show_timing = &show_timing;
930local show_completed = &show_completed;
931local verbose_mode = &verbose_mode;
932local show_other_areas = &show_other_areas;
933local show_up_down = &show_up_down;
934local show_area_exits = &show_area_exits;
935local speedwalk_prefix = "&speedwalk_prefix;"
936local prefer_shown = true
937
938
939<![CDATA[
940
941require "serialize"
942require "copytable"
943require "wait"
944require "gmcphelper"
945
946
947function file_exists(path)
948 local f = io.open(path, "r")
949
950 if (f) then
951 io.close(f)
952 return true
953 else
954 return false
955 end
956end
957
958
959if (file_exists(GetInfo(66) .. "lua/mm_mapper.lua")) then
960 mapper = require "mm_mapper"
961else
962 require "mapper"
963end
964
965
966rooms = {}
967--areas = {}
968
969local fontcol = "silver"
970local bgcol = "black"
971
972
973
974-- --------------
975-- plugin stuff
976-- --------------
977
978function OnPluginInstall()
979 wait.make(function()
980 config = {} -- in case not found
981
982 -- get saved configuration
983 assert(loadstring(GetVariable("config") or ""))()
984
985 -- allow for additions to config
986 for k, v in pairs(default_config) do
987 config[k] = config[k] or v
988 end
989
990 -- initialize mapper
991 mapper.init {
992 config = config,
993 get_room = get_room,
994 show_help = OnHelp, -- to show help
995 room_click = room_click, -- called on RH click on room square
996 timing = show_timing, -- want to see timing
997 show_completed = show_completed, -- want to see "Speedwalk completed." message
998 show_other_areas = show_other_areas, -- want to see areas other than the current one?
999 show_up_down = show_up_down, -- want to follow up/down exits?
1000 show_area_exits = show_area_exits, -- want to see area exits?
1001 speedwalk_prefix = speedwalk_prefix, -- how to speedwalk
1002 }
1003
1004 mapper.mapprint(string.format("MUSHclient mapper installed, version %0.1f", mapper.VERSION))
1005
1006 -- open database on disk
1007 if (file_exists(GetInfo(66) .. "mm_mapper.db"))
1008 or (not file_exists(GetInfo(66) .. Trim(WorldAddress()) .. "_mapper.db")) then
1009 db = assert(sqlite3.open(GetInfo(66) .. "mm_mapper.db"))
1010 compatibility = false
1011
1012 elseif (file_exists(GetInfo(66) .. Trim(WorldAddress()) .. "_mapper.db")) then
1013 ColourTell("white", "maroon", "GMCP Mapper WARNING: type ")
1014 ColourTell("lime", "maroon", "mapper upgrade database")
1015 ColourNote("white", "maroon", " to convert your old maps database file to the new structure.")
1016 ColourNote("silver", "black", "(This process may take several minutes, during which the client will seem to be 'frozen'.)")
1017 ColourNote("white", "maroon", "NOTICE that the mapper might NOT warn you about CPK rooms until you have upgraded the database.")
1018 db = assert(sqlite3.open(GetInfo(66) .. Trim(WorldAddress()) .. "_mapper.db"))
1019 compatibility = true
1020 end
1021
1022 create_tables() -- create database structure if necessary
1023
1024 Tell("-- " .. GetPluginInfo(GetPluginID(), 1) .. ": type ")
1025 ColourTell("silver", "black", GetPluginInfo(GetPluginID(), 1) .. " help")
1026 Note(" to see info about this plugin --")
1027
1028 room_not_in_database = {}
1029
1030 first_room = true
1031
1032 load_config2()
1033
1034 -- give the plugins time to initialize
1035 wait.time(3)
1036
1037 detect_plugins()
1038 end)
1039end
1040
1041
1042function OnPluginSaveState()
1043 mapper.save_state()
1044 SetVariable("config", "config = " .. serialize.save_simple(config))
1045end
1046
1047
1048function OnPluginClose()
1049 mapper.hide()
1050end
1051
1052
1053function OnPluginDisable()
1054 mapper.hide()
1055end
1056
1057
1058function OnPluginListChanged()
1059 detect_plugins()
1060end
1061
1062
1063function detect_plugins()
1064 use_events_mini = events_mini_installed()
1065 reader_present = detect_reader()
1066 sapi_present = sapi_plugin_present()
1067end
1068
1069
1070function is_plugin_present(name, id)
1071 local res = false
1072
1073 local plugin_name = GetPluginInfo(id, 1)
1074
1075 if (plugin_name == name) then
1076 -- is it enabled?
1077 if (GetPluginInfo(id, 17)) then
1078 res = true
1079 end
1080 end
1081
1082 return res
1083end
1084
1085
1086function plugin_update_url()
1087 local t = {
1088 "https://raw.githubusercontent.com/mu3r73/mm-mushclient-scripts/master/src/MM_GMCP_Mapper_GMCP.xml",
1089 }
1090 return (table.concat(t, ";"))
1091end
1092
1093
1094function plugin_update_aux_url()
1095 local t = {
1096 "https://raw.githubusercontent.com/mu3r73/mm-mushclient-scripts/master/src/mm_mapper.lua,MUSH/lua",
1097 }
1098 return (table.concat(t, ";"))
1099end
1100
1101
1102
1103---------
1104-- help
1105---------
1106
1107function OnHelp()
1108 mapper.mapprint(string.format("[MUSHclient mapper, version %0.1f]", mapper.VERSION))
1109 ColourNote("silver", "black", world.GetPluginInfo(world.GetPluginID(), 3))
1110 Note("")
1111 ColourNote("silver", "black", "(this version: " .. os.date("%c", GetPluginInfo(GetPluginID(), 14)) .. ")")
1112end
1113
1114
1115function help_maintenance()
1116 ColourNote("silver", "black", world.GetPluginInfo(world.GetPluginID(), 3))
1117 ColourNote("silver", "black", [[> Advanced Maintenance/Privacy Aliases
1118
1119> config:
1120
1121* mapper reset defaults - use to restore default settings, if necessary
1122* mapper show database mods [on|off] - toggle showing database updates on/off (on by default)
1123
1124> queries:
1125
1126* mapper roominfo [<room#>] - show info about a room
1127
1128* mapper export rooms <name> - exports all rooms matching the name
1129* mapper export area <name> - exports a whole area
1130
1131> additions:
1132
1133* mapper addroom <room#> n:<name> a:<area> f:<flags> t:<terrain> ti:<terraininfo> - add a room
1134
1135* mapper addexit <dir> [f:<from_room#>] t:<to_room#> - add an exit to a room
1136
1137* mapper addbm [<room#>] [b:<text>] - add a bookmark
1138
1139> deletions:
1140
1141* mapper delroom <room#> - delete a room
1142
1143* mapper delexit <dir> [f:<from_room#>] - delete an exit from a room
1144* mapper delexits <from_room#> - delete all exits from a room
1145
1146* mapper delbm [<room#>] - delete a bookmark
1147
1148> tags:
1149
1150* mapper dt [<room#>] - tag room as DT
1151* mapper trap [<room#>] - tag room as trap
1152* mapper no-speed [<room#>] - tag room as no-speed
1153* mapper shop [<room#>] - tag room as shop
1154* mapper trainer [<room#>] - tag room as trainer
1155
1156> privacy:
1157
1158* mapper purge clanhalls - purge clanhalls data from the database
1159* mapper purge homes - purge player homes data from the database
1160* mapper purge bookmarks - purge all non-vmap notes from the database
1161
1162> rebuild data:
1163
1164* mapper recreate database - copy data to a new database file
1165* mapper rebuild lookup - rebuild the rooms_lookup table
1166
1167]])
1168
1169end
1170
1171
1172
1173-- ---------------
1174-- GMCP broadcast
1175-- ---------------
1176
1177function OnPluginBroadcast(msg, id, name, text)
1178 if (id =="f67c4339ed0591a5b010d05b") then -- GMCP message
1179 if (text == "room.info") then -- room.info
1180 peeking = false
1181 purge_cache_if_area_changed()
1182
1183 get_gmcp_room()
1184 process_room()
1185 end
1186 end
1187end
1188
1189
1190
1191---------------
1192-- GMCP stuff
1193---------------
1194
1195function get_gmcp_room()
1196 local res, gmcparg = CallPlugin("f67c4339ed0591a5b010d05b", "gmcpval", "room.info")
1197 luastmt = "gmcpdata = " .. gmcparg
1198
1199 assert(loadstring(luastmt or ""))()
1200end
1201
1202
1203
1204-- ----------------------
1205-- default configuration
1206-- ----------------------
1207
1208function reset_defaults()
1209 config = {}
1210
1211 for k, v in pairs(default_config) do
1212 config[k] = v
1213 end
1214
1215 -- initialize mapper
1216 mapper.init {
1217 config = config,
1218 get_room = get_room,
1219 show_help = OnHelp, -- to show help
1220 room_click = room_click, -- called on RH click on room square
1221 timing = show_timing, -- want to see timing
1222 show_completed = show_completed, -- want to see "Speedwalk completed." message
1223 show_other_areas = show_other_areas, -- want to see areas other than the current one?
1224 show_up_down = show_up_down, -- want to follow up/down exits?
1225 show_area_exits = show_area_exits, -- want to see area exits?
1226 speedwalk_prefix = speedwalk_prefix, -- how to speedwalk
1227 }
1228end
1229
1230
1231default_config = {
1232 -- assorted colours
1233 BACKGROUND_COLOUR = {
1234 name = "Background",
1235 colour = ColourNameToRGB "cadetblue",
1236 },
1237 ROOM_COLOUR = {
1238 name = "Room",
1239 colour = ColourNameToRGB "cyan",
1240 },
1241 EXIT_COLOUR = {
1242 name = "Exit",
1243 colour = ColourNameToRGB "darkgreen",
1244 },
1245 EXIT_COLOUR_UP_DOWN = {
1246 name = "Exit up/down",
1247 colour = ColourNameToRGB "darkmagenta",
1248 },
1249 OUR_ROOM_COLOUR = {
1250 name = "Our room",
1251 colour = ColourNameToRGB "black",
1252 },
1253 UNKNOWN_ROOM_COLOUR = {
1254 name = "Unknown room",
1255 colour = ColourNameToRGB "#00CACA",
1256 },
1257 DIFFERENT_AREA_COLOUR = {
1258 name = "Another area",
1259 colour = ColourNameToRGB "gray",
1260 },
1261 DT_FILL_COLOUR = {
1262 name = "DT",
1263 colour = ColourNameToRGB "black",
1264 },
1265 SAFE_FILL_COLOUR = {
1266 name = "Safe",
1267 colour = ColourNameToRGB "white",
1268 },
1269 SHOP_FILL_COLOUR = {
1270 name = "Shop",
1271 colour = ColourNameToRGB "yellow",
1272 },
1273 TRAINER_FILL_COLOUR = {
1274 name = "Trainer",
1275 colour = ColourNameToRGB "mediumpurple"
1276 },
1277 LPK_FILL_COLOUR = {
1278 name = "LPK",
1279 colour = ColourNameToRGB "lightcoral"
1280 },
1281 NPK_FILL_COLOUR = {
1282 name = "NPK",
1283 colour = ColourNameToRGB "tomato"
1284 },
1285 CPK_FILL_COLOUR = {
1286 name = "CPK",
1287 colour = ColourNameToRGB "darkred"
1288 },
1289 DIZZY_COLOUR = {
1290 name = "Dizzy",
1291 colour = ColourNameToRGB "blue"
1292 },
1293 FEAR_COLOUR = {
1294 name = "Fear",
1295 colour = ColourNameToRGB "yellow"
1296 },
1297 TRAP_COLOUR = {
1298 name = "Dizzy",
1299 colour = ColourNameToRGB "red"
1300 },
1301 DIGGABLE_FILL_COLOUR = {
1302 name = "diggable",
1303 colour = ColourNameToRGB "wheat"
1304 },
1305 WOODED_FILL_COLOUR = {
1306 name = "wooded",
1307 colour = ColourNameToRGB "seagreen"
1308 },
1309 UNDERWATER_FILL_COLOUR = {
1310 name = "underwater",
1311 colour = ColourNameToRGB "steelblue"
1312 },
1313 FREEZING_FILL_COLOUR = {
1314 name = "freezing",
1315 colour = ColourNameToRGB "lightcyan"
1316 },
1317 FIRE_FILL_COLOUR = {
1318 name = "fire",
1319 colour = ColourNameToRGB "red"
1320 },
1321 POISON_FILL_COLOUR = {
1322 name = "poison-gas",
1323 colour = ColourNameToRGB "yellowgreen"
1324 },
1325 ACID_FILL_COLOUR = {
1326 name = "acid",
1327 colour = ColourNameToRGB "greenyellow"
1328 },
1329 NOTHING_FILL_COLOUR = {
1330 name = "nothing",
1331 colour = ColourNameToRGB "deepskyblue"
1332 },
1333
1334 ROOM_NAME_TEXT = {
1335 name = "Room name text",
1336 colour = ColourNameToRGB "#BEF3F1",
1337 },
1338 ROOM_NAME_FILL = {
1339 name = "Room name fill",
1340 colour = ColourNameToRGB "#105653",
1341 },
1342 ROOM_NAME_BORDER = {
1343 name = "Room name box",
1344 colour = ColourNameToRGB "black",
1345 },
1346
1347 AREA_NAME_TEXT = {
1348 name = "Area name text",
1349 colour = ColourNameToRGB "#BEF3F1",
1350 },
1351 AREA_NAME_FILL = {
1352 name = "Area name fill",
1353 colour = ColourNameToRGB "#105653",
1354 },
1355 AREA_NAME_BORDER = {
1356 name = "Area name box",
1357 colour = ColourNameToRGB "black",
1358 },
1359
1360 FONT = {
1361 name = get_preferred_font {
1362 "Dina",
1363 "Lucida Console",
1364 "Fixedsys",
1365 "Courier",
1366 "Sylfaen",
1367 },
1368 size = 8.
1369 },
1370
1371 -- size of map window
1372 WINDOW = {
1373 width = 400,
1374 height = 261
1375 },
1376
1377 -- how far from where we are standing to draw (rooms)
1378 SCAN = {
1379 depth = 250
1380 },
1381
1382 -- speedwalk delay
1383 DELAY = {
1384 time = 0
1385 },
1386
1387 -- how many seconds to show "recent visit" lines (default 3 minutes)
1388 LAST_VISIT_TIME = {
1389 time = 60 * 3
1390 },
1391}
1392
1393
1394
1395-- -----------------
1396-- specific config
1397-- -----------------
1398
1399function load_config2()
1400 config2 = {
1401 visible = ((GetVariable("mapper_visible") or "true") == "true"),
1402 auto_open = ((GetVariable("auto_open") or "true") == "true"),
1403 safewalk = ((GetVariable("safewalk") or "false") == "true"),
1404 color_terrain = ((GetVariable("color_terrain") or "false") == "true"),
1405 do_map_wilds = ((GetVariable("do_map_wilds") or "false") == "true"),
1406 show_database_mods = ((GetVariable("show_database_mods") or "true") == "true"),
1407 show_flags = ((GetVariable("show_flags") or "false") == "true"),
1408 show_numbers = ((GetVariable("show_numbers") or "false") == "true"),
1409 vis_road_exits = ((GetVariable("vis_road_exits") or "false") == "true"),
1410 vis_unmapped_exits = ((GetVariable("vis_unmapped_exits") or "false") == "true"),
1411 draw_other_floors = ((GetVariable("draw_other_floors") or "true") == "true"),
1412 -- this last variable overrides config.show_up_down
1413 }
1414
1415 if (not config2.visible) then
1416 mapper.hide()
1417 end
1418end
1419
1420
1421function save_config2()
1422 SetVariable("mapper_visible", tostring(config2.visible))
1423 SetVariable("auto_open", tostring(config2.auto_open))
1424 SetVariable("safewalk", tostring(config2.safewalk))
1425 SetVariable("color_terrain", tostring(config2.color_terrain))
1426 SetVariable("do_map_wilds", tostring(config2.do_map_wilds))
1427 SetVariable("show_database_mods", tostring(config2.show_database_mods))
1428 SetVariable("show_flags", tostring(config2.show_flags))
1429 SetVariable("show_numbers", tostring(config2.show_numbers))
1430 SetVariable("vis_road_exits", tostring(config2.vis_road_exits))
1431 SetVariable("vis_unmapped_exits", tostring(config2.vis_unmapped_exits))
1432 SetVariable("draw_other_floors", tostring(config2.draw_other_floors))
1433
1434 SaveState()
1435end
1436
1437
1438
1439-- ---------------------------
1440-- mapper 'get_room' callback
1441-- ---------------------------
1442
1443function get_room(uid)
1444 -- check we got room at all
1445 if (not uid) then
1446 return nil
1447 end
1448
1449 -- look it up
1450 local ourroom = rooms[uid]
1451
1452 -- not cached - see if in database
1453 if (not ourroom) then
1454 ourroom = load_room_from_database(uid)
1455 end -- not in cache
1456
1457 if (not ourroom) then
1458 return nil
1459 end
1460
1461 local room = copytable.deep(ourroom)
1462
1463 -- build hover message
1464
1465 local flags = room.flags
1466 if (not flags) or (flags == "") then
1467 flags = "-"
1468 end
1469
1470 local terrain = room.terrain
1471 if (not terrain) or (terrain == "") then
1472 terrain = "-"
1473 end
1474
1475 local terraininfo = room.terraininfo
1476 if (not terraininfo) or (terraininfo == "") then
1477 terraininfo = "-"
1478 end
1479
1480 local notes = room.notes
1481 if (not room.notes) or (room.notes == "") then
1482 notes = "-"
1483 end -- if notes
1484
1485 local tags = room.tags
1486 if (not tags) or (room.tags == "") then
1487 tags = "-"
1488 end -- if DT
1489
1490 local texits = {}
1491 for dir in pairs(room.exits) do
1492 table.insert(texits, dir)
1493 end -- for
1494 table.sort(texits)
1495
1496 room.hovermessage = string.format(
1497 "%s\tExits: %s\nGMCP #: %s\nFlags: %s\nTerrain: %s (%s)\nTags: %s\nBookmarks: %s",
1498 room.name,
1499 table.concat(texits, ", "),
1500 uid,
1501 flags,
1502 terrain,
1503 terraininfo,
1504 tags,
1505 notes
1506 )
1507
1508 room.bordercolour = config.ROOM_COLOUR.colour
1509 room.borderpen = 0 -- solid
1510 room.borderpenwidth = 1
1511
1512 -- special room fill colours
1513
1514 if (has_flag(room.flags, "safe")) then
1515 room.fillcolour = config.SAFE_FILL_COLOUR.colour
1516 room.fillbrush = 8
1517
1518 elseif (has_flag(room.flags, "player-kill-chaotic")) then
1519 room.fillcolour = config.CPK_FILL_COLOUR.colour
1520 room.fillbrush = 8
1521
1522 elseif (has_tag(room.tags, "dt")) then
1523 room.fillcolour = config.DT_FILL_COLOUR.colour
1524 room.fillbrush = 8
1525
1526 elseif (has_tag(room.tags, "trainer")) then
1527 room.fillcolour = config.TRAINER_FILL_COLOUR.colour
1528 room.fillbrush = 8
1529
1530 elseif (has_tag(room.tags, "shop")) then
1531 room.fillcolour = config.SHOP_FILL_COLOUR.colour
1532 room.fillbrush = 8
1533
1534 elseif (has_flag(room.flags, "player-kill-neutral")) then
1535 room.fillcolour = config.NPK_FILL_COLOUR.colour
1536 room.fillbrush = 8
1537
1538 elseif (has_flag(room.flags, "player-kill-lawful")) then
1539 room.fillcolour = config.LPK_FILL_COLOUR.colour
1540 room.fillbrush = 8
1541
1542 elseif (string.find(terraininfo, "underwater")) then
1543 room.fillcolour = config.UNDERWATER_FILL_COLOUR.colour
1544 room.fillbrush = 8
1545
1546 elseif (string.find(terraininfo, "wooded")) then
1547 room.fillcolour = config.WOODED_FILL_COLOUR.colour
1548 room.fillbrush = 8
1549
1550 elseif (string.find(terraininfo, "freezing")) then
1551 room.fillcolour = config.FREEZING_FILL_COLOUR.colour
1552 room.fillbrush = 8
1553
1554 elseif (string.find(terraininfo, "fire")) then
1555 room.fillcolour = config.FIRE_FILL_COLOUR.colour
1556 room.fillbrush = 8
1557
1558 elseif (string.find(terraininfo, "poison")) then
1559 room.fillcolour = config.POISON_FILL_COLOUR.colour
1560 room.fillbrush = 8
1561
1562 elseif (string.find(terraininfo, "acid")) then
1563 room.fillcolour = config.ACID_FILL_COLOUR.colour
1564 room.fillbrush = 8
1565
1566 elseif (string.find(terraininfo, "diggable")) then
1567 room.fillcolour = config.DIGGABLE_FILL_COLOUR.colour
1568 room.fillbrush = 8
1569
1570 elseif (string.find(terraininfo, "nothing")) then
1571 room.fillcolour = config.NOTHING_FILL_COLOUR.colour
1572 room.fillbrush = 8
1573
1574 else
1575 room.fillcolour = 0xff0000
1576 room.fillbrush = 1 -- no fill
1577 end
1578
1579 -- terrain is always shown in non-pk
1580 -- however, in all-pk areas, pk colors prevail over terrain colors
1581 -- config2.color_terrain toggles terrain coloring for pk areas
1582 if (config2.color_terrain) then
1583 if (string.find(terraininfo, "underwater")) then
1584 room.fillcolour = config.UNDERWATER_FILL_COLOUR.colour
1585 room.fillbrush = 8
1586
1587 elseif (string.find(terraininfo, "wooded")) then
1588 room.fillcolour = config.WOODED_FILL_COLOUR.colour
1589 room.fillbrush = 8
1590
1591 elseif (string.find(terraininfo, "freezing")) then
1592 room.fillcolour = config.FREEZING_FILL_COLOUR.colour
1593 room.fillbrush = 8
1594
1595 elseif (string.find(terraininfo, "fire")) then
1596 room.fillcolour = config.FIRE_FILL_COLOUR.colour
1597 room.fillbrush = 8
1598
1599 elseif (string.find(terraininfo, "poison")) then
1600 room.fillcolour = config.POISON_FILL_COLOUR.colour
1601 room.fillbrush = 8
1602
1603 elseif (string.find(terraininfo, "acid")) then
1604 room.fillcolour = config.ACID_FILL_COLOUR.colour
1605 room.fillbrush = 8
1606
1607 elseif (string.find(terraininfo, "diggable")) then
1608 room.fillcolour = config.DIGGABLE_FILL_COLOUR.colour
1609 room.fillbrush = 8
1610
1611 elseif (string.find(terraininfo, "nothing")) then
1612 room.fillcolour = config.NOTHING_FILL_COLOUR.colour
1613 room.fillbrush = 8
1614
1615 else
1616 room.fillcolour = 0xff0000
1617 room.fillbrush = 1 -- no fill
1618 end
1619 end -- config2.color_terrain
1620
1621 if (room.area ~= current_area) then
1622 room.bordercolour = config.DIFFERENT_AREA_COLOUR.colour
1623
1624 elseif (has_tag(room.tags, "trap")) then
1625 room.bordercolour = config.TRAP_COLOUR.colour
1626
1627 elseif (has_flag(room.flags, "disorient")) then
1628 room.bordercolour = config.DIZZY_COLOUR.colour
1629
1630 elseif (has_flag(room.flags, "fear")) then
1631 room.bordercolour = config.FEAR_COLOUR.colour
1632 end
1633
1634 if (uid == current_room) then
1635 if (not has_flag(room.flags, "disorient"))
1636 and (not has_flag(room.flags, "fear")) then
1637 room.bordercolour = config.OUR_ROOM_COLOUR.colour
1638 end
1639 room.borderpenwidth = 2
1640 end
1641
1642 return room
1643end
1644
1645
1646
1647----------------------
1648-- gui main function
1649----------------------
1650
1651function room_click(uid, flags)
1652 -- check we got room at all
1653 if (not uid) then
1654 return nil
1655 end
1656
1657 -- look it up
1658 local room = rooms[uid]
1659
1660 -- not cached - see if in database
1661 if (not room) then
1662 room = load_room_from_database(uid)
1663 end -- not in cache
1664
1665 if (not room) then
1666 return
1667 end -- if still not there
1668
1669 local handlers = {
1670 { name = "Edit bookmark", func = room_edit_bookmark} ,
1671 { name = "-", } ,
1672 { name = "Add Exit", func = room_add_exit} ,
1673 { name = "Change Exit", func = room_change_exit} ,
1674 { name = "Delete Exit", func = room_delete_exit} ,
1675 { name = "-", } ,
1676 { name = "Toggle DT", func = room_toggle_tag, tag = "dt" } ,
1677 { name = "Toggle No-Speed", func = room_toggle_tag, tag = "no-speed" } ,
1678 { name = "Toggle Shop", func = room_toggle_tag, tag = "shop" } ,
1679 { name = "Toggle Trainer", func = room_toggle_tag, tag = "trainer" } ,
1680 { name = "Toggle Trap", func = room_toggle_tag, tag = "trap" } ,
1681 } -- handlers
1682
1683 local t, tf = {}, {}
1684 for _, v in pairs(handlers) do
1685 table.insert(t, v.name)
1686 tf[v.name] = v
1687 end -- for
1688
1689 local choice = WindowMenu(mapper.win,
1690 WindowInfo(mapper.win, 14),
1691 WindowInfo(mapper.win, 15),
1692 table.concat(t, "|"))
1693
1694 local f = tf[choice]
1695
1696 if f then
1697 f.func(room, uid, f.tag)
1698 end -- if handler found
1699end
1700
1701
1702
1703--------------------
1704-- interface stuff
1705--------------------
1706
1707function mapper_show(prefer)
1708 config2.visible = true
1709 save_config2()
1710
1711 if (prefer) then
1712 prefer_shown = true
1713 end
1714
1715 if (prefer_shown) then
1716 mapper.show()
1717 end
1718end
1719
1720
1721function mapper_hide(prefer)
1722 config2.visible = false
1723 save_config2()
1724
1725 if (prefer) then
1726 prefer_shown = false
1727 end
1728
1729 mapper.hide()
1730end
1731
1732
1733function toggle_terrain_to(status)
1734 config2.color_terrain = do_toggle(config2.color_terrain, status)
1735
1736 save_config2()
1737
1738 if (config2.color_terrain) then
1739 Note("-- MM_GMCP_Mapper: showing terrain color only --")
1740 else
1741 Note("-- MM_GMCP_Mapper: PK/shop/trainer color supersedes terrain color --")
1742 end
1743
1744 mapper.draw(current_room)
1745end
1746
1747
1748function toggle_vis_flags_to(status)
1749 config2.show_flags = do_toggle(config2.show_flags, status)
1750
1751 save_config2()
1752
1753 if (config2.show_flags) then
1754 Note("-- MM_GMCP_Mapper: showing room flags and terrain ON --")
1755 else
1756 Note("-- MM_GMCP_Mapper: showing room flags and terrain OFF --")
1757 end
1758end
1759
1760
1761function toggle_vis_number_to(status)
1762 config2.show_numbers = do_toggle(config2.show_numbers, status)
1763
1764 save_config2()
1765
1766 if (config2.show_numbers) then
1767 Note("-- MM_GMCP_Mapper: showing and logging room numbers ON --")
1768 else
1769 Note("-- MM_GMCP_Mapper: showing and logging room numbers OFF --")
1770 end
1771end
1772
1773
1774function toggle_vis_road_exits_to(status)
1775 config2.vis_road_exits = do_toggle(config2.vis_road_exits, status)
1776
1777 save_config2()
1778
1779 if (config2.vis_road_exits) then
1780 Note("-- MM_GMCP_Mapper: showing road exits ON --")
1781 else
1782 Note("-- MM_GMCP_Mapper: showing road exits OFF --")
1783 end
1784end
1785
1786
1787function toggle_vis_unmapped_to(status)
1788 config2.vis_unmapped_exits = do_toggle(config2.vis_unmapped_exits, status)
1789
1790 save_config2()
1791
1792 if (config2.vis_unmapped_exits) then
1793 Note("-- MM_GMCP_Mapper: showing unmapped exits ON --")
1794 else
1795 Note("-- MM_GMCP_Mapper: showing unmapped exits OFF --")
1796 end
1797end
1798
1799
1800function toggle_draw_other_floors_to(status)
1801 config2.draw_other_floors = do_toggle(config2.draw_other_floors, status)
1802
1803 save_config2()
1804
1805 if (config2.draw_other_floors) then
1806 mapper.toggle_show_up_down(true)
1807 Note("-- MM_GMCP_Mapper: drawing other floors ON --")
1808 else
1809 mapper.toggle_show_up_down(false)
1810 Note("-- MM_GMCP_Mapper: drawing other floors OFF --")
1811 end
1812end
1813
1814
1815function toggle_auto_open_to(status)
1816 config2.auto_open = do_toggle(config2.auto_open, status)
1817
1818 save_config2()
1819
1820 if (config2.auto_open) then
1821 Note("-- MM_GMCP_Mapper: auto-open doors ON --")
1822 else
1823 Note("-- MM_GMCP_Mapper: auto-open doors OFF --")
1824 end
1825end
1826
1827
1828function toggle_safewalk_to(status)
1829 config2.safewalk = do_toggle(config2.safewalk, status)
1830
1831 save_config2()
1832
1833 if (config2.safewalk) then
1834 Note("-- MM_GMCP_Mapper: safewalk mode ON --")
1835 else
1836 Note("-- MM_GMCP_Mapper: safewalk mode OFF --")
1837 end
1838end
1839
1840
1841function toggle_show_database_mods_to(status)
1842 config2.show_database_mods = do_toggle(config2.show_database_mods, status)
1843
1844 save_config2()
1845
1846 if (config2.show_database_mods) then
1847 Note("-- MM_GMCP_Mapper: showing database mods ON --")
1848 else
1849 Note("-- MM_GMCP_Mapper: showing database mods OFF --")
1850 end
1851end
1852
1853
1854function do_toggle(var, status)
1855 if (status == "on") then
1856 var = true
1857 elseif (status == "off") then
1858 var = false
1859 else
1860 var = not var
1861 end
1862
1863 return var
1864end
1865
1866
1867function check_if_show_flags_and_terrain(flags, terrain)
1868 if (config2.show_flags) then
1869 show_flags_and_terrain(flags, terrain)
1870 end
1871end
1872
1873
1874function show_flags_and_terrain(flags, terrain)
1875 local show_flags = flags
1876 if (not show_flags) or (show_flags == "") then
1877 show_flags = "-"
1878 end
1879
1880 local show_terrain = terrain
1881 if (not show_terrain) or (show_terrain == "") then
1882 show_terrain = "-"
1883 end
1884
1885 Note("[gmcp: " .. show_flags .. " / " .. show_terrain .. "]")
1886end
1887
1888
1889function check_if_show_room_number(exits)
1890 local texits = utils.split(Trim(exits), " ")
1891
1892 if (config2.show_numbers) or (texits[1] == "?") or (texits[1] == "None.") then
1893 show_room_number()
1894 end
1895end
1896
1897
1898function show_room_number()
1899 if (uid) then
1900 Note("[gmcp #" .. uid .. "]")
1901 WriteLog("[gmcp #" .. uid .. "]")
1902 end
1903end
1904
1905
1906function check_if_show_road_exits()
1907 if (config2.vis_road_exits) and (is_vmap()) then
1908 show_road_exits()
1909 end
1910end
1911
1912
1913function show_road_exits()
1914 local dest, room, ok_exits
1915
1916 ok_exits = {}
1917
1918 for dir in string.gmatch(exits_str, "%a+") do
1919 dest = gmcpval("exits." .. dir)
1920
1921 room = load_room_from_database(dest)
1922
1923 if (room) then
1924 ok_exits[#ok_exits + 1] = capitalize(dir)
1925 end
1926 end -- for each exit
1927
1928 ok_exits = Trim(table.concat(ok_exits, " "))
1929
1930 if (ok_exits ~= "") then
1931 Tell(" on-road exits: ")
1932 ColourNote("silver", "black", ok_exits)
1933 end
1934end
1935
1936
1937function check_if_show_unmapped_exits()
1938 if (config2.vis_unmapped_exits) and (not is_vmap()) then
1939 show_unmapped_exits()
1940 end
1941end
1942
1943
1944function show_unmapped_exits()
1945 local dest, room, ok_exits
1946
1947 unmapped_exits = {}
1948 one_way_exits = {}
1949
1950 local uid = gmcpval("num")
1951
1952 for dir in string.gmatch(exits_str, "%a+") do
1953 dest = gmcpval("exits." .. dir)
1954
1955 room = load_room_from_database(dest)
1956
1957 if (not room) then
1958 unmapped_exits[#unmapped_exits + 1] = capitalize(dir)
1959
1960 else
1961 local links_back = false
1962
1963-- Tell("exits from " .. dest .. ": ")
1964-- Note(serialize.save_simple(room.exits))
1965
1966 for dir, num in pairs(room.exits) do
1967 if (num == uid) then
1968 links_back = true
1969 break
1970 end
1971 end
1972
1973 if (not links_back) then
1974 one_way_exits[#one_way_exits + 1] = capitalize(dir)
1975 end
1976 end
1977 end -- for each exit
1978
1979 unmapped_exits = Trim(table.concat(unmapped_exits, " "))
1980 if (unmapped_exits ~= "") then
1981 Tell(" unmapped exits: ")
1982 ColourNote("silver", "black", unmapped_exits)
1983 end
1984
1985 one_way_exits = Trim(table.concat(one_way_exits, " "))
1986 if (one_way_exits ~= "") then
1987 Tell(" one way exits: ")
1988 ColourNote("silver", "black", one_way_exits)
1989 end
1990end
1991
1992
1993function peek_room(id)
1994 local room = load_room_from_database(id)
1995
1996 if (room) then -- room is in the map
1997 peeking = true
1998 peeking_from = id
1999 Send("rest")
2000 mapper.mapprint("Peeking room", id, "... Type 'look' to return to normal view.")
2001 if (verbose_mode) then
2002 Note("(making you rest so if you click on a room, you won't start a wrong speedwalk)")
2003 end
2004 mapper.draw(id)
2005
2006 else
2007 mapper.mapprint("The room", id, "isn't in the map.")
2008 end
2009end
2010
2011
2012function notify_teleport()
2013 Note("-- mapper: wait for teleport... --")
2014end
2015
2016
2017function notify_portal()
2018 Note("-- mapper: enter portal/mirror/gate/etching/... --")
2019
2020 BroadcastPlugin(1, "portal")
2021end
2022
2023
2024
2025------------
2026-- queries
2027------------
2028
2029function map_where(rname)
2030 local sname = fixsql("%" .. string.upper(rname) .. "%")
2031 local t = {}
2032
2033 for row in db:nrows(string.format("SELECT uid, area FROM rooms WHERE UPPER(name) like %s", sname)) do
2034 if (not is_vmap(row.area)) then
2035 t[#t + 1] = row.uid
2036 end
2037 end -- finding rooms
2038
2039 ColourNote("lightgreen", "black", "Results for: '" .. rname .. "':")
2040 show_hyperlinks(t)
2041 if (verbose_mode) then
2042 ColourNote("lightgreen", "black", "Click on a room's name or type 'mapper goto <id>' to speedwalk to the room, if possible.")
2043 end
2044end
2045
2046
2047function map_wheree(rname, area)
2048 local sname = fixsql(string.upper(rname))
2049 local t = {}
2050
2051 area = Trim(area)
2052
2053 for row in db:nrows(string.format("SELECT uid, area FROM rooms WHERE UPPER(name) = %s", sname)) do
2054 if (not is_vmap(row.area)) and (area ~= "") then
2055 if (string.lower(row.area) == string.lower(area)) then
2056 t[#t + 1] = row.uid
2057 end
2058 else
2059 t[#t + 1] = row.uid
2060 end
2061 end -- finding rooms
2062
2063 ColourTell("lightgreen", "black", "Results for: '" .. rname .. "'")
2064 if (area ~= "") then
2065 ColourNote("lightgreen", "black", " in the area: '" .. area .. "':")
2066 else
2067 ColourNote("lightgreen", "black", ":")
2068 end
2069
2070 show_hyperlinks(t)
2071
2072 if (area ~= "") then
2073 ColourTell("lightgreen", "black", "Click ")
2074 Hyperlink("mapper wheree " .. rname, "[here]", "", "lightgreen", "black", false)
2075 ColourNote("lightgreen", "black", " or type 'mapper wheree " .. rname .. "' to repeat the search without area restrictions.")
2076 end
2077end
2078
2079
2080function get_room_areas(rname)
2081 local sname = fixsql(string.upper(rname))
2082 local t = {}
2083
2084 for row in db:nrows(string.format("SELECT area FROM rooms WHERE UPPER(name) = %s", sname)) do
2085 t[#t + 1] = row.area
2086 end -- finding rooms
2087
2088 return table.concat(t, ";")
2089end
2090
2091
2092function map_find(keywords)
2093 if (not peeking) then
2094 local rooms = {}
2095 local count = 0
2096 local snippets = {}
2097 local reset = ANSI(0)
2098 local bold = ANSI(1)
2099 local unbold = ANSI(22)
2100 local red = ANSI(31)
2101
2102 function show_snippet(uid)
2103 local room = rooms[uid]
2104 if (not room) then
2105 room = load_room_from_database(uid)
2106 end
2107
2108 local cpk = ""
2109 if (has_flag(room.flags, "player-kill-chaotic")) then
2110 cpk = red .. bold .. " [CPK]"
2111 end
2112
2113 if (not reader_present) then
2114 AnsiNote(reset .. snippets[uid], cpk, reset .. " @ " .. room.area)
2115 else
2116 Note(StripANSI(snippets[uid] .. cpk .. " @ " .. room.area))
2117 end
2118 end
2119
2120 -- find matching rooms using FTS3
2121 for row in db:nrows(string.format(
2122 [[
2123 SELECT uid, name, snippet(rooms_lookup, '%s', '%s', ' ... ', -1, -10) AS snippet
2124 FROM rooms_lookup
2125 WHERE rooms_lookup MATCH %s]],
2126 bold, unbold,
2127 fixsql(keywords))) do
2128 rooms[row.uid] = true
2129 snippets[row.uid] = row.snippet
2130 count = count + 1
2131 end -- finding room
2132
2133 -- see if nearby
2134 mapper.find(
2135 function (uid)
2136 local room = rooms[uid]
2137 if room then
2138 rooms[uid] = nil
2139 end
2140 return room, next(rooms) == nil
2141 end, -- function
2142 show_vnums, -- show vnum?
2143 count, -- how many to expect
2144 false, -- don't auto-walk
2145 config2.safewalk,
2146 show_snippet -- show find snippet
2147 )
2148 end
2149end
2150
2151
2152function map_bookmarks(name, line, wildcards)
2153 if (compatibility) then
2154 ColourNote("tomato", "black", "GMCP Mapper: I can't find bookmarks in compatibility mode. Please upgrade your database.")
2155
2156 else
2157 local rooms = {}
2158 local count = 0
2159
2160 -- build table of special places (with info in them)
2161 for row in db:nrows(string.format("SELECT uid FROM rooms WHERE area = %s", fixsql(zone))) do
2162 local anote = load_notes_from_database(row.uid)
2163 if (anote) and (anote ~= "") then
2164 rooms[row.uid] = capitalize(anote)
2165 count = count + 1
2166 end
2167 end -- finding room
2168
2169 -- find such places
2170 mapper.find(
2171 function (uid)
2172 local room = rooms[uid]
2173 if room then
2174 rooms[uid] = nil
2175 end
2176 return room, next(rooms) == nil -- room will be type of info(eg. shop)
2177 end, -- function
2178 show_vnums, -- show vnum?
2179 count, -- how many to expect
2180 false, -- don't auto-walk
2181 config2.safewalk
2182 )
2183 end
2184end
2185
2186
2187function map_find_bookmark(book)
2188 if (compatibility) then
2189 ColourNote("tomato", "black", "GMCP Mapper: I can't find bookmarks in compatibility mode. Please upgrade your database.")
2190
2191 else
2192 local sbook = "%" .. string.upper(book) .. "%"
2193 local t = {}
2194
2195 for row in db:nrows(string.format('SELECT * FROM bookmarks WHERE UPPER(notes) like "%s"', sbook)) do
2196 local room = load_room_from_database(row.uid)
2197 if (room.area == current_area) then
2198 t[#t + 1] = row.uid
2199 end
2200 end -- finding rooms
2201
2202 ColourNote("lightgreen", "black", "Rooms bookmarked as: '" .. sbook .. "':")
2203 show_hyperlinks(t)
2204
2205 if (verbose_mode) then
2206 ColourNote("lightgreen", "black", "Click on a room's name or type 'mapper goto <id>' to speedwalk to the room, if possible.")
2207 end
2208 end
2209end
2210
2211
2212function map_list_by_flags(flags)
2213 local sflags = utils.split(flags, " ")
2214 local rarea = current_area
2215 local t = {}
2216 local rflags
2217
2218 local use_column = "flags"
2219 if (compatibility) then
2220 use_column = "description"
2221 end
2222
2223 for row in db:nrows(string.format('SELECT uid, %s FROM rooms WHERE area = "%s"', use_column, rarea)) do
2224 local use_field = row.flags
2225 if (compatibility) then
2226 use_field = row.description
2227 end
2228 rflags = string.gsub(use_field or "", " ", "")
2229 rflags = utils.split(rflags, ",")
2230
2231 if (has_all(sflags, rflags)) then
2232 t[#t + 1] = row.uid
2233 end
2234 end -- finding rooms
2235
2236 mapper.mapprint("Results for flag(s)", flags, "in the area", rarea)
2237 show_hyperlinks(t)
2238
2239 if (verbose_mode) then
2240 mapper.mapprint("Click on a room's name or type 'mapper goto <id>' to speedwalk to the room, if possible.")
2241 end
2242end
2243
2244
2245function has_all(sflags, rflags)
2246 local res
2247 local tres = {}
2248
2249 for i = 1, #sflags do
2250-- Note(sflags[i])
2251 tres[i] = false
2252
2253 for j = 1, #rflags do
2254-- Note(rflags[j])
2255 if (sflags[i] == rflags[j]) then
2256 tres[i] = true
2257 end
2258 end
2259 end
2260
2261 res = true
2262 for i = 1, #tres do
2263 res = res and tres[i]
2264 end
2265
2266 return res
2267end
2268
2269
2270function has_none(sflags, rflags)
2271 local res
2272 local tres = {}
2273
2274 for i = 1, #sflags do
2275-- Note(sflags[i])
2276 tres[i] = false
2277
2278 for j = 1, #rflags do
2279-- Note(rflags[j])
2280 if (sflags[i] == rflags[j]) then
2281 tres[i] = true
2282 end
2283 end
2284 end
2285
2286 res = true
2287 for i = 1, #tres do
2288 res = res and (not tres[i])
2289 end
2290
2291 return res
2292end
2293
2294
2295function map_list_by_not_flags(flags)
2296 local sflags = utils.split(flags, " ")
2297 local rarea = current_area
2298 local t = {}
2299 local rflags
2300
2301 local use_column = "flags"
2302 if (compatibility) then
2303 use_column = "description"
2304 end
2305
2306 for row in db:nrows(string.format('SELECT uid, name, %s FROM rooms WHERE area = "%s"', use_column, rarea)) do
2307 local use_field = row.flags
2308 if (compatibility) then
2309 use_field = row.description
2310 end
2311 rflags = string.gsub(use_field or "", " ", "")
2312 rflags = utils.split(rflags, ",")
2313
2314 if (has_none(sflags, rflags)) then
2315 t[#t + 1] = row.uid
2316 end
2317 end -- finding rooms
2318
2319 mapper.mapprint("Results for NOT flag(s)", flags, "in the area", rarea)
2320 show_hyperlinks(t)
2321
2322 if (verbose_mode) then
2323 mapper.mapprint("Click on a room's name or type 'mapper goto <id>' to speedwalk to the room, if possible.")
2324 end
2325end
2326
2327
2328function map_hyperlink(id)
2329 local t = {id}
2330 show_hyperlinks(t)
2331end
2332
2333
2334function show_hyperlinks(t)
2335 table.sort(t)
2336 local rflags
2337
2338 for i = 1, #t do
2339-- Note(t[i])
2340 local room = rooms[t[i]]
2341 if (not room) then
2342 room = load_room_from_database(t[i])
2343 end
2344
2345 Tell("room: ")
2346 Hyperlink ("mapper goto " .. t[i], room.name, "", "white", bgcol, false)
2347
2348 if (has_flag(room.flags, "player-kill-chaotic")) then
2349 ColourTell("red", bgcol, " [CPK]")
2350 end
2351
2352 Tell(" - id: ")
2353 ColourTell(fontcol, bgcol, t[i])
2354
2355 if (room.area ~= "-") then
2356 Tell(" - area: ")
2357 ColourTell(fontcol, bgcol, room.area)
2358-- Hyperlink("gate " .. room.area, room.area, "", fontcol, bgcol, false)
2359 end
2360
2361 Note("")
2362 end
2363end
2364
2365
2366function map_show_adjacent_rooms(name)
2367 local sname = fixsql(string.upper(Trim(name)))
2368
2369 -- find matching rooms
2370 local taux = {}
2371
2372 for row in db:nrows(string.format("SELECT uid FROM rooms WHERE UPPER(name) = %s", sname)) do
2373 taux[#taux + 1] = row.uid
2374 end
2375
2376 mapper.mapprint("Adjacent rooms for name =", name)
2377
2378 if (#taux == 0) then
2379 Note("No rooms by that name in my db.")
2380 return
2381 end
2382
2383 table.sort(taux)
2384
2385 -- find adjacent exits with names /= name
2386 local tres = {}
2387 local thisroom, adjroom
2388
2389 for i = 1, #taux do
2390 thisroom = load_room_from_database(taux[i])
2391
2392 for _, num in pairs(thisroom.exits) do
2393 adjroom = load_room_from_database(num)
2394
2395 if (adjroom)
2396 and (string.upper(Trim(adjroom.name)) ~= string.upper(Trim(name))) then
2397 tres[#tres + 1] = "(" .. adjroom.area .. ") " .. adjroom.name
2398 end
2399 end
2400 end
2401
2402 -- show results, if any
2403 if (#tres > 0) then
2404 table.sort(tres)
2405
2406 for i = 1, #tres do
2407 ColourNote("silver", "black", tres[i])
2408 end
2409
2410 else
2411 Note("No matches.")
2412 end
2413end
2414
2415
2416function map_safe()
2417 if (not peeking) then
2418 map_list_by_flags("safe")
2419 end
2420end
2421
2422
2423function map_cpk()
2424 if (not peeking) then
2425 map_list_by_flags("player-kill-chaotic")
2426 end
2427end
2428
2429
2430function map_dts()
2431 if (not peeking) then
2432 if (not compatibility) then
2433 map_list_by_tags("dt")
2434 else
2435 ColourNote("tomato", "black", "GMCP Mapper: I can't search rooms with the DT tag in compatibility mode. Please upgrade your database.")
2436 end
2437 end
2438end
2439
2440
2441function map_shops()
2442 if (not peeking) then
2443 if (not compatibility) then
2444 map_list_by_tags("shop")
2445 else
2446 map_list_by_tags_compat("shop")
2447 end
2448 end
2449end
2450
2451
2452function map_trainers()
2453 if (not peeking) then
2454 if (not compatibility) then
2455 map_list_by_tags("trainer")
2456 else
2457 map_list_by_tags_compat("train")
2458 end
2459 end
2460end
2461
2462
2463function map_list_by_tags(tags)
2464 local stags = utils.split(tags, " ")
2465 local rarea = current_area
2466 local t = {}
2467 local room, rtags
2468
2469 for row in db:nrows(string.format('SELECT * FROM player_tags')) do
2470 room = do_load_room(row.uid)
2471
2472 if (room.area == rarea) then
2473 rtags = row.tags
2474 rtags = string.gsub(rtags or "", " ", "")
2475 rtags = utils.split(rtags, ",")
2476
2477 if (has_all(stags, rtags)) then
2478 t[#t + 1] = row.uid
2479 end
2480 end
2481 end -- finding rooms
2482
2483 mapper.mapprint("Results for tag(s)", tags, "in the area", rarea)
2484 show_hyperlinks(t)
2485
2486 if (verbose_mode) then
2487 mapper.mapprint("Click on a room's name or type 'mapper goto <id>' to speedwalk to the room, if possible.")
2488 end
2489end
2490
2491
2492function map_list_by_tags_compat(which)
2493 local rooms = {}
2494 local count = 0
2495
2496 -- build table of special places (with info in them)
2497 for row in db:nrows(string.format("SELECT uid, name FROM rooms WHERE %s = 1", which)) do
2498 rooms[row.uid] = true
2499 count = count + 1
2500 end -- finding room
2501
2502 -- find such places
2503 mapper.find(
2504 function (uid)
2505 local room = rooms[uid]
2506 if room then
2507 rooms[uid] = nil
2508 end
2509 return room, next(rooms) == nil -- room will be type of info (eg. shop)
2510 end, -- function
2511 show_vnums, -- show vnum?
2512 count, -- how many to expect
2513 false, -- don't auto-walk
2514 config2.safewalk
2515 )
2516end
2517
2518
2519
2520-------------
2521-- movement
2522-------------
2523
2524function map_path(wanted)
2525 return map_path2(current_room, wanted)
2526end
2527
2528
2529function map_path2(fromuid, touid)
2530 if not mapper.check_we_can_find() then
2531 return
2532 end
2533
2534 if fromuid and touid == fromuid then
2535 mapper.mapprint("You are already in that room.")
2536 return
2537 end
2538
2539 local old_depth = config.SCAN.depth
2540 config.SCAN.depth = 2500
2541
2542 local paths = mapper.find_paths(fromuid,
2543 function (uid)
2544 return uid == touid, -- wanted room?
2545 uid == touid -- stop searching?
2546 end)
2547
2548 local uid, item = next(paths, nil) -- extract first (only) path
2549
2550 config.SCAN.depth = old_depth
2551
2552 -- nothing? room not found
2553 if not item then
2554 mapper.mapprint(string.format("Path from %s to %s not found.", fromuid, touid))
2555 return
2556 end
2557
2558 -- turn into speedwalk
2559 local path = mapper.build_speedwalk(item.path)
2560
2561 -- display it
2562 path = string.gsub(path, "tprt", "teleport")
2563 path = string.gsub(path, "prtl", "portal")
2564
2565 mapper.mapprint(string.format("Path from %s to %s is: %s", fromuid, touid, path))
2566
2567 return path
2568end
2569
2570
2571function map_goto(wanted)
2572-- -- check valid string
2573-- if string.match(wanted, "%D") then
2574-- mapper.maperror("Room number must be a number, you entered: " .. wanted)
2575-- return
2576-- end
2577
2578 -- see if the room is mapped
2579 local room = load_room_from_database(wanted)
2580 if (not room) then
2581 mapper.mapprint("That room is not mapped.")
2582 return
2583 end
2584
2585 -- see if already there
2586 if current_room and (current_room == wanted) then
2587 mapper.mapprint("You are already in that room.")
2588 return
2589 end
2590
2591 local old_depth = config.SCAN.depth
2592
2593 if (is_vmap(zone))
2594 or (zone ~= room.area) then
2595 config.SCAN.depth = 2500
2596 else
2597 config.SCAN.depth = 500
2598 end
2599
2600 -- find desired room
2601 mapper.find(
2602 function (uid)
2603 local found = string.match(uid, "^" .. wanted .. "$")
2604 return found, found
2605 end, -- function
2606 show_vnums, -- show vnum?
2607 1, -- how many to expect
2608 true, -- just walk there
2609 config2.safewalk
2610 )
2611
2612 config.SCAN.depth = old_depth
2613end
2614
2615
2616function map_resume(name, line, wildcards)
2617 local wanted = mapper.last_hyperlink_uid or mapper.last_speedwalk_uid
2618
2619 if (wanted) then
2620 map_goto(wanted)
2621
2622 elseif (not wanted) then
2623 mapper.mapprint("No outstanding speedwalks or hyperlinks.")
2624 end -- if nothing to do
2625end
2626
2627
2628function map_speedwalk_next(name, line, wildcards)
2629 local next = mapper.get_next_dir()
2630
2631 if (next) then
2632 if (sapi_present) then
2633 if (string.lower(next) == "teleport") then
2634 sapi_say("wait for teleport")
2635 elseif (string.lower(next) == "portal") then
2636 sapi_say("enter portal")
2637 else
2638 sapi_say(next)
2639 end
2640
2641 else
2642 Note("* next speedwalk direction: " .. next)
2643 end
2644 end
2645end
2646
2647
2648
2649-- ---------------------------------
2650-- process room (as we walk, etc.)
2651-- ---------------------------------
2652
2653function process_room()
2654 uid = gmcpval("num")
2655 zone = gmcpval("zone")
2656
2657 if (uid ~= "") then
2658-- Note(uid)
2659
2660 if (uid) then
2661 roomname = gmcpval("name")
2662
2663 roomflags = gmcpval("flags")
2664 if (roomflags == "_empty") then
2665 roomflags = nil
2666 end
2667
2668 exits = {}
2669 exits_str = gmcp_get_exits()
2670
2671 current_area = zone
2672
2673 terrain = gmcpval("terrain")
2674 terraininfo = gmcpval("terraininfo")
2675
2676 check_if_show_flags_and_terrain(roomflags, terrain)
2677
2678 current_room = uid
2679
2680 local room = rooms[current_room]
2681 if (not room) then -- not cached
2682 room = load_room_from_database(current_room) -- try to load room from db
2683 end
2684
2685 if (not room) then -- room isn't mapped yet
2686 if (config2.do_map_wilds) -- we're mapping everything
2687 or ((not is_vmap(zone) or (is_road(terrain) and not is_cave(roomname)))) then -- it's not in the wilds
2688 db:exec("BEGIN TRANSACTION;")
2689
2690 save_room_to_database(current_room, roomname, roomflags, zone, terrain, terraininfo)
2691 save_exits_to_database(zone, current_room, exits_str)
2692
2693 db:exec("COMMIT;")
2694
2695 room = load_room_from_database(current_room) -- get it back now
2696
2697 -- for fixes to outdated maps, run 'mapper update room'
2698 end
2699
2700 else -- room already mapped, update if needed
2701 update_room(uid)
2702 end
2703 end
2704
2705 first_room = false
2706 end
2707
2708 if (uid) -- we're not in a maze
2709 and ((config2.do_map_wilds) -- we're mapping the wilds
2710 or ((not is_vmap(zone) or (is_road(terrain) and not is_cave(roomname))))) then
2711 -- or we're in a part of the wilds that we always wanna map
2712 mapper.draw(current_room) -- call mapper to draw this rom
2713 end
2714end
2715
2716
2717
2718-------------------
2719-- various checks
2720-------------------
2721
2722function purge_cache_if_area_changed()
2723 local zone = gmcpval("zone")
2724
2725 if (zone ~= old_zone) then
2726 rooms = {}
2727 old_zone = zone
2728 room_not_in_database = {}
2729 end
2730end
2731
2732
2733function has_flag(flags, flag)
2734 local aux
2735 aux = flags or ""
2736 aux = string.gsub(aux, escaped_str("no-" .. flag), "x")
2737 return (string.find(aux, escaped_str(flag)) ~= nil)
2738end
2739
2740
2741function escaped_str(s)
2742 s = string.gsub(s, "%-", "%%-")
2743 return s
2744end
2745
2746
2747function has_tag(tags, tag)
2748 return (string.find(tags or "", escaped_str(tag)) ~= nil)
2749end
2750
2751
2752function is_true(x)
2753 local res
2754
2755 x = fixbool(x)
2756 if (x == 1) then
2757 res = true
2758 end
2759
2760 return res
2761end
2762
2763
2764function is_vmap(zone)
2765 local vmap_zones = {
2766 ["alyria"] = true,
2767 ["chat rooms wilderness"] = true,
2768 ["faerie plane wilderness"] = true,
2769 ["great alyrian underground"] = true,
2770 ["lasler valley"] = true,
2771 ["sigil underground"] = true,
2772 ["verity isle"] = true,
2773 }
2774
2775 local res
2776
2777 if (not zone) then
2778 local code = gmcpval("coord.code")
2779 res = (code ~= "")
2780
2781 else
2782 res = vmap_zones[string.lower(Trim(zone))]
2783 end
2784
2785 return res
2786end
2787
2788
2789function is_cave(name)
2790 local cave_names = {
2791 ["subterranean cave"] = true,
2792 ["subterranean caves"] = true,
2793 ["caves of darkness and shadow"] = true,
2794 }
2795
2796 return cave_names[string.lower(name)]
2797end
2798
2799
2800function is_road(terrain)
2801 local road_terrains = {
2802 ["bridge"] = true,
2803 ["city street"] = true,
2804 ["dusty road"] = true,
2805 ["gravel road"] = true,
2806 ["mountain-road"] = true,
2807 ["paved road"] = true,
2808 ["trail"] = true,
2809 }
2810
2811 return road_terrains[string.lower(terrain)]
2812end
2813
2814
2815function is_valid_direction(dir)
2816 local dirs = {
2817 ["ne"] = true,
2818 ["e"] = true,
2819 ["se"] = true,
2820 ["s"] = true,
2821 ["sw"] = true,
2822 ["w"] = true,
2823 ["nw"] = true,
2824 ["n"] = true,
2825 ["u"] = true,
2826 ["d"] = true,
2827 ["tprt"] = true,
2828 ["prtl"] = true,
2829 }
2830 return(dirs[dir] ~= nil)
2831end
2832
2833
2834function is_volatile(uid)
2835 local volatile = {
2836 ["10328"] = "Feral Wolverine Mother", -- Mandrake Woods
2837 ["12242"] = "A Dark Alcove", -- Rune Forest
2838 ["12258"] = "A Frozen Passage", -- Rune Forest
2839 ["16334"] = "A Small, Nondescript Cave", -- Limbo Maze
2840 ["17835"] = "Broad Corridor [chemwalker]", -- Deceit
2841 ["22434"] = "The Wandering Sidhe",
2842 ["25835"] = "The Wicker Undercarriage of the Airship Inconvenience",
2843 ["28637"] = "A Cramped Room [illusionist]", -- Sigil
2844-- ["49837"] = "Spiral Staircase", -- Riga
2845 ["67734"] = "A Concealed Spiral Stair [Idolatry]", -- Catacombs of Shame
2846 ["68323"] = "A Quartz Cave [tourmaline dragon]", -- Maldra Keep
2847 ["68263"] = "Preacher Dan's House of Vandynity", -- Maldra Keep
2848 ["78413"] = "Maze Passageway [angel]", -- HH
2849 ["107527"] = "A Hidden Torture Room", -- Hellbent
2850 }
2851
2852 local x = volatile[tostring(uid)]
2853
2854 if (x) then
2855 add_to_events_mini("room #" .. current_room .. ": " .. x)
2856 end
2857
2858 return (x ~= nil)
2859end
2860
2861
2862function add_to_events_mini(txt)
2863 function add_style_to_events_mini(fgcol, bgcol, txt)
2864 CallPlugin("9ced43d0a7b4a60116794096", "add_to_mini", fgcol, bgcol, txt)
2865 end
2866
2867 -- OnPluginListChanged() should keep 'use_events_mini' updated
2868
2869 if (use_events_mini) then
2870 add_style_to_events_mini("dodgerblue", "black", txt)
2871 add_style_to_events_mini("silver", "black", "\r\n")
2872 end
2873end
2874
2875
2876function events_mini_installed()
2877 return is_plugin_present("events_mini", "9ced43d0a7b4a60116794096")
2878end
2879
2880
2881
2882------------------------
2883-- specific GMCP stuff
2884------------------------
2885
2886function gmcp_get_exits()
2887 local shortdir = {"n", "nw", "w", "sw", "s", "se", "e", "ne", "u", "d"}
2888
2889 local exits, i, res, touid, doort
2890
2891 doort = gmcpval("exits")
2892
2893 if (string.find(serialize.save_simple(doort) or "", "hidden")) then
2894 ColourNote("blueviolet", "black", "[gmcp: hidden exit!]")
2895 end
2896
2897 if (string.find(serialize.save_simple(doort) or "", "buried")) then
2898 ColourNote("blueviolet", "black", "[gmcp: buried exit!]")
2899 end
2900
2901 if (string.find(serialize.save_simple(doort) or "", "illusion%-disguised")) then
2902 ColourNote("blueviolet", "black", "[gmcp: illus exit!]")
2903 end
2904
2905 exits = ""
2906 for i = 1, #shortdir do
2907 touid = gmcpval("exits." .. shortdir[i])
2908
2909 if (touid ~= "") then
2910 if (exits == "") then
2911 exits = shortdir[i]
2912 else
2913 exits = exits .. " " .. shortdir[i]
2914 end
2915 end
2916 end
2917
2918 return exits
2919end
2920
2921
2922
2923------------------------
2924-- database management
2925------------------------
2926
2927function dbcheck(code)
2928 if code ~= sqlite3.OK and -- no error
2929 code ~= sqlite3.ROW and -- completed OK with another row of data
2930 code ~= sqlite3.DONE then -- completed OK, no more rows
2931 local err = db:errmsg() -- the rollback will change the error message
2932 db:exec("ROLLBACK") -- rollback any transaction to unlock the database
2933 error(err, 2) -- show error in caller's context
2934 end
2935end
2936
2937
2938function fixsql(s)
2939 if s then
2940 return "'" .. (string.gsub(s, "'", "''")) .. "'" -- replace single quotes with two lots of single quotes
2941 else
2942 return "NULL"
2943 end
2944end
2945
2946
2947function fixbool(b)
2948 if ((b == true) or (b == "yes") or (b == 1) or (b == "1")) then
2949 b = 1
2950 elseif ((b == false) or (b == "no") or (b == 0) or (b == "0") or (not b)) then -- fix for old maps that used different values
2951 b = 0
2952 end
2953 return b
2954end
2955
2956
2957function create_tables()
2958 -- create rooms table
2959 -- and create rooms_lookup table, if it doesn't exist
2960 if (not compatibility) then
2961 create_tables_new(db)
2962 create_rooms_lookup_new(db)
2963 else
2964 create_tables_compatibility(db)
2965 create_rooms_lookup_compatibility(db)
2966 end
2967end
2968
2969
2970function create_tables_new(use_db)
2971 dbcheck(use_db:execute[[
2972
2973 PRAGMA foreign_keys = ON;
2974 PRAGMA journal_mode = WAL;
2975
2976 CREATE TABLE IF NOT EXISTS rooms(
2977 uid TEXT NOT NULL, -- vnum or how the MUD identifies the room
2978 name TEXT, -- name of room
2979 flags TEXT, -- room flags
2980 area TEXT, -- which area it is in
2981 terrain TEXT, -- terrain
2982 terraininfo TEXT, -- terrain info
2983 date_added DATE, -- date added to database
2984 UNIQUE(uid)
2985 );
2986
2987 CREATE TABLE IF NOT EXISTS bookmarks(
2988 uid TEXT NOT NULL, -- room's vnum
2989 notes TEXT, -- player notes
2990 UNIQUE(uid),
2991 FOREIGN KEY(uid) REFERENCES rooms(uid)
2992 );
2993
2994 CREATE TABLE IF NOT EXISTS player_tags(
2995 uid TEXT NOT NULL, -- room's vnum
2996 tags TEXT, -- player tags (DT, no-speed, shop, trainer, trap)
2997 UNIQUE(uid),
2998 FOREIGN KEY(uid) REFERENCES rooms(uid)
2999 );
3000
3001 CREATE TABLE IF NOT EXISTS exits(
3002 dir TEXT NOT NULL, -- direction, eg. "n", "s"
3003 fromuid TEXT NOT NULL, -- exit from which room(in rooms table)
3004 touid TEXT NOT NULL, -- exit to which room(in rooms table)
3005 date_added DATE, -- date added to database
3006 FOREIGN KEY(fromuid) REFERENCES rooms(uid)
3007 );
3008 CREATE INDEX IF NOT EXISTS fromuid_index ON exits(fromuid);
3009 CREATE INDEX IF NOT EXISTS touid_index ON exits(touid);
3010 ]])
3011end
3012
3013
3014function create_tables_compatibility(use_db)
3015 dbcheck(use_db:execute[[
3016
3017 PRAGMA foreign_keys = ON;
3018 PRAGMA journal_mode = WAL;
3019
3020 CREATE TABLE IF NOT EXISTS rooms(
3021 roomid INTEGER PRIMARY KEY AUTOINCREMENT,
3022 uid TEXT NOT NULL, -- vnum or how the MUD identifies the room
3023 name TEXT, -- name of room
3024 description TEXT, -- room flags
3025 area TEXT, -- which area it is in
3026 terrain TEXT, -- terrain
3027 terraininfo TEXT, -- terrain info
3028 safe INTEGER, -- 1 = safe room
3029 lpk INTEGER, -- 1 = lpk room
3030 npk INTEGER, -- 1 = npk room
3031 cpk INTEGER, -- 1 = cpk room
3032 shop INTEGER, -- 1 = shop here
3033 train INTEGER, -- 1 = trainer here
3034 notes TEXT, -- player notes
3035 date_added DATE, -- date added to database
3036 UNIQUE(uid)
3037 );
3038 CREATE INDEX IF NOT EXISTS safe_index ON rooms(safe);
3039 CREATE INDEX IF NOT EXISTS cpk_index ON rooms(cpk);
3040 CREATE INDEX IF NOT EXISTS shop_index ON rooms(shop);
3041 CREATE INDEX IF NOT EXISTS train_index ON rooms(train);
3042
3043 CREATE TABLE IF NOT EXISTS exits(
3044 exitid INTEGER PRIMARY KEY AUTOINCREMENT,
3045 dir TEXT NOT NULL, -- direction, eg. "n", "s"
3046 fromuid TEXT NOT NULL, -- exit from which room(in rooms table)
3047 touid TEXT NOT NULL, -- exit to which room(in rooms table)
3048 date_added DATE, -- date added to database
3049 FOREIGN KEY(fromuid) REFERENCES rooms(uid)
3050 );
3051 CREATE INDEX IF NOT EXISTS fromuid_index ON exits(fromuid);
3052 CREATE INDEX IF NOT EXISTS touid_index ON exits(touid);
3053
3054 ]])
3055end
3056
3057
3058function create_rooms_lookup_new(use_db)
3059 local table_exists
3060 for a in use_db:nrows "SELECT * FROM sqlite_master WHERE name = 'rooms_lookup' AND type = 'table'" do
3061 table_exists = true
3062 end
3063
3064 if not table_exists then
3065 dbcheck(use_db:execute "CREATE VIRTUAL TABLE rooms_lookup USING FTS3(uid, name, area);")
3066 -- in case we only deleted the rooms_lookup table to save space in the download
3067 dbcheck(use_db:execute "INSERT INTO rooms_lookup(uid, name, area) SELECT uid, name, area FROM rooms;")
3068 end
3069end
3070
3071
3072function create_rooms_lookup_compatibility(use_db)
3073 local table_exists
3074 for a in use_db:nrows "SELECT * FROM sqlite_master WHERE name = 'rooms_lookup' AND type = 'table'" do
3075 table_exists = true
3076 end
3077
3078 if not table_exists then
3079 dbcheck(use_db:execute "CREATE VIRTUAL TABLE rooms_lookup USING FTS3(uid, name, description);")
3080 -- in case we only deleted the rooms_lookup table to save space in the download
3081 dbcheck(use_db:execute "INSERT INTO rooms_lookup(uid, name, description) SELECT uid, name, description FROM rooms;")
3082 end
3083end
3084
3085
3086
3087---------------------
3088-- database queries
3089---------------------
3090
3091function load_room_from_database(uid)
3092 assert(uid, "No UID supplied to load_room_from_database")
3093
3094 if (room_not_in_database[uid]) then
3095 return nil
3096 end -- no point looking
3097
3098 local room = do_load_room(uid)
3099
3100 if (room) then
3101 rooms[uid] = room
3102 room_not_in_database[uid] = nil
3103 return room
3104 end -- if found
3105
3106 room_not_in_database[uid] = true
3107 return nil
3108end
3109
3110
3111function do_load_room(uid)
3112 local room
3113
3114 for row in db:nrows(string.format("SELECT * FROM rooms WHERE uid = %s", fixsql(uid))) do
3115 room = {
3116 name = row.name,
3117 area = row.area,
3118 terrain = row.terrain,
3119 terraininfo = row.terraininfo,
3120 date_added = row.date_added,
3121 exits = {}
3122 }
3123
3124 if (not compatibility) then
3125 room.flags = row.flags
3126 room.notes = load_notes_from_database(uid)
3127 room.tags = load_tags_from_database(uid)
3128
3129 else
3130 room.flags = row.description
3131 room.flags = fix_flag(room.flags, row.safe, "safe")
3132 room.flags = fix_flag(room.flags, row.lpk, "player-kill-lawful")
3133 room.flags = fix_flag(room.flags, row.npk, "player-kill-neutral")
3134 room.flags = fix_flag(room.flags, row.cpk, "player-kill-chaotic")
3135
3136 room.notes = row.notes
3137
3138 room.tags = ""
3139 room.tags = fix_tag(room.tags, row.shop, "shop")
3140 room.tags = fix_tag(room.tags, row.train, "trainer")
3141 end
3142
3143 for exitrow in db:nrows(string.format("SELECT * FROM exits WHERE fromuid = %s", fixsql(uid))) do
3144 room.exits[exitrow.dir] = tostring(exitrow.touid)
3145 end -- for each exit
3146 end -- finding room
3147
3148 return room
3149end
3150
3151
3152function room_exits(uid)
3153 local room = rooms[uid]
3154 if (not room) then
3155 room = load_room_from_database(uid)
3156 end
3157
3158 local res = ""
3159 if (room) then
3160 res = serialize.save_simple(room.exits or {})
3161 end
3162
3163 return res
3164end
3165
3166
3167function fix_flag(flags, field, flag)
3168 if (is_true(field))
3169 and (not has_flag(flags, flag)) then
3170 flags = add_a_flag(flags, flag)
3171 end
3172
3173 return flags
3174end
3175
3176
3177function fix_tag(tags, field, tag)
3178 if (is_true(field))
3179 and (not has_tag(tags, tag)) then
3180 tags = add_a_tag(tags, tag)
3181 end
3182
3183 return tags
3184end
3185
3186
3187function add_a_flag(flags, flag)
3188 return add_a_tag(flags, flag)
3189end
3190
3191
3192function load_notes_from_database(uid)
3193 local res
3194
3195 for row in db:nrows(string.format("SELECT * FROM bookmarks WHERE uid = %s", fixsql(uid))) do
3196 res = row.notes
3197 end
3198
3199 return res
3200end
3201
3202
3203function load_tags_from_database(uid)
3204 local res
3205
3206 for row in db:nrows(string.format("SELECT * FROM player_tags WHERE uid = %s", fixsql(uid))) do
3207 res = row.tags
3208 end
3209
3210 return res
3211end
3212
3213
3214
3215-- -----------
3216-- additions
3217-- -----------
3218
3219--------------
3220-- add rooms
3221--------------
3222
3223function map_add_room(id, name, zone, flags, terrain, terraininfo)
3224 local room = load_room_from_database(id)
3225
3226 if (not room) then -- room isn't mapped yet
3227 db:exec("BEGIN TRANSACTION;")
3228
3229 save_room_to_database(id, Trim(name), Trim(flags), Trim(zone), Trim(terrain), Trim(terraininfo))
3230
3231 db:exec("COMMIT;")
3232
3233 -- update in-memory table
3234 load_room_from_database(id)
3235
3236 mapper.draw(current_room)
3237
3238 else
3239 mapper.mapprint("The room", id, "is already mapped.")
3240 end
3241end
3242
3243
3244function save_room_to_database(uid, title, flags, area, terrain, terraininfo)
3245 assert(uid, "No UID supplied to save_room_to_database")
3246
3247 local use_column = "flags"
3248 if (compatibility) then
3249 use_column = "description"
3250 end
3251
3252 dbcheck(db:execute(string.format(
3253 "INSERT INTO rooms(uid, name, %s, area, terrain, terraininfo, date_added) VALUES(%s, %s, %s, %s, %s, %s, DATETIME('NOW'));",
3254 use_column,
3255 fixsql(uid),
3256 fixsql(title),
3257 fixsql(flags),
3258 fixsql(area),
3259 fixsql(terrain),
3260 fixsql(terraininfo)
3261 )))
3262
3263 use_column = "area"
3264 local use_field = area
3265 if (compatibility) then
3266 use_column = "flags"
3267 use_field = flags
3268 end
3269
3270 dbcheck(db:execute(string.format(
3271 "INSERT INTO rooms_lookup(uid, name, %s) VALUES(%s, %s, %s);",
3272 use_column,
3273 fixsql(uid),
3274 fixsql(title),
3275 fixsql(use_field)
3276 )))
3277
3278 room_not_in_database[uid] = nil
3279
3280 if (config2.show_database_mods) then
3281 mapper.mapprint("Added room", uid, "to database. Name:", title)
3282 end
3283end
3284
3285
3286
3287------------------
3288-- add bookmarks
3289------------------
3290
3291function map_add_bookmark(id, new_note)
3292 if (compatibility) then
3293 ColourNote("tomato", "black", "GMCP Mapper: I can't edit bookmarks in compatibility mode. Please upgrade your database.")
3294
3295 else
3296 if (id == "") then
3297 id = uid -- current room is default
3298 end
3299
3300 if (new_note == "") then
3301 new_note = "x"
3302 end
3303
3304 local room = load_room_from_database(id)
3305
3306 if (room) then -- room is in the map
3307 db:exec("BEGIN TRANSACTION;")
3308
3309 local notes = load_notes_from_database(id)
3310
3311 if (notes) then -- room already has a bookmark
3312 update_bookmark(id, new_note)
3313 mapper.mapprint("Bookmark for room", uid, "changed to:", new_note)
3314 else
3315 save_bookmark(id, new_note)
3316 mapper.mapprint("Bookmark for room", id, "set to:", new_note)
3317 end
3318
3319 db:exec("COMMIT;")
3320
3321 -- update in-memory table
3322 if (rooms[id]) then
3323 rooms[id].notes = new_note
3324 end
3325
3326 else
3327 mapper.mapprint("The room", id, "isn't in the map.")
3328 end
3329 end
3330end
3331
3332
3333function room_edit_bookmark(room, uid)
3334-- gui function
3335 if (compatibility) then
3336 ColourNote("tomato", "black", "GMCP Mapper: I can't edit bookmarks in compatibility mode. Please upgrade your database.")
3337
3338 else
3339 local notes = room.notes or ""
3340
3341 if (notes ~= "") then
3342 newnotes = utils.inputbox("Modify room comment (clear it to delete from database)", room.name, notes)
3343 else
3344 newnotes = utils.inputbox("Enter room comment (creates a bookmark for this room)", room.name, notes)
3345 end
3346
3347 if (not newnotes) then
3348 return
3349 end -- if cancelled
3350
3351 if (notes ~= newnotes) then
3352 if (newnotes == "") then
3353 if (notes == "") then
3354 mapper.mapprint("No comment entered, bookmark not saved.")
3355 else
3356 del_bookmark_from_database(uid)
3357 mapper.mapprint("Bookmark for room", uid, "deleted. Was previously:", notes)
3358
3359 -- update in-memory table
3360 if (rooms[id]) then
3361 rooms[id].notes = nil
3362 end
3363 end
3364
3365 else -- newnotes not empty
3366 if (notes == "") then
3367 save_bookmark(uid, newnotes)
3368 mapper.mapprint("Bookmark added to room", uid, ":", newnotes)
3369 else
3370 update_bookmark(uid, newnotes)
3371 mapper.mapprint("Bookmark for room", uid, "changed to:", newnotes)
3372 end
3373
3374 -- update in-memory table
3375 if (rooms[id]) then
3376 rooms[id].notes = newnotes
3377 end
3378 end
3379 end
3380 end
3381end
3382
3383
3384function save_bookmark(uid, notes)
3385 dbcheck(db:execute(string.format(
3386 "INSERT INTO bookmarks(uid, notes) VALUES(%s, %s);",
3387 fixsql(uid),
3388 fixsql(notes)
3389 )))
3390end
3391
3392
3393
3394-------------
3395-- add tags
3396-------------
3397
3398function save_tags_to_database(uid, tags)
3399 dbcheck(db:execute(string.format(
3400 "INSERT INTO player_tags(uid, tags) VALUES(%s, %s);",
3401 fixsql(uid),
3402 fixsql(tags)
3403 )))
3404end
3405
3406
3407
3408--------------
3409-- add exits
3410--------------
3411
3412function map_add_exit(dir, fromid, toid)
3413 if (fromid == "") then
3414 fromid = uid -- current room is default
3415 end
3416
3417 local room = load_room_from_database(fromid)
3418
3419 if (room) then -- room fromid is in the map
3420 if (is_valid_direction(dir)) then
3421 if (not is_volatile(toid)) then
3422 db:exec("BEGIN TRANSACTION;")
3423
3424 add_exit_to_database(dir, fromid, toid)
3425
3426 db:exec("COMMIT;")
3427
3428 -- update in-memory table
3429 if (rooms[fromid]) then
3430 if (not rooms[fromid].exits) then
3431 rooms[fromid].exits = {}
3432 end
3433
3434 rooms[fromid].exits[dir] = toid
3435 end
3436
3437 mapper.draw(current_room)
3438
3439 else
3440 mapper.mapprint("The room", toid, "changes locations.")
3441 end
3442
3443 else
3444 mapper.mapprint("You must provide a valid direction (n, ne, etc.)")
3445 end
3446
3447 else
3448 mapper.mapprint("The room", fromid, "isn't in the map.")
3449 end
3450end
3451
3452
3453function add_exit_to_database(dir, fromuid, touid)
3454 assert(dir, "No direction supplied to add_exit_to_database")
3455 assert(fromuid, "No fromUID supplied to add_exit_to_database")
3456 assert(touid, "No toUID supplied to add_exit_to_database")
3457
3458 dbcheck(db:execute(string.format(
3459 "INSERT INTO exits(dir, fromuid, touid, date_added) VALUES(%s, %s, %s, DATETIME('NOW'));",
3460 fixsql(dir), -- direction (eg. "n")
3461 fixsql(fromuid), -- from room
3462 fixsql(touid) -- destination room
3463 )))
3464
3465 if (config2.show_database_mods) then
3466 mapper.mapprint("Added exit to database,", dir, "from", fromuid, "to", touid)
3467 end
3468end
3469
3470
3471function save_exits_to_database(zone, uid, exits)
3472 local dest
3473
3474 for dir in string.gmatch(exits, "%a+") do
3475 dest = gmcpval("exits." .. dir)
3476
3477 if (dest ~= "-99") then
3478 dbcheck(db:execute(string.format(
3479 "INSERT INTO exits(dir, fromuid, touid, date_added) VALUES(%s, %s, %s, DATETIME('NOW'));",
3480 fixsql(dir), -- direction (eg. "n")
3481 fixsql(uid), -- from current room
3482 fixsql(dest) -- destination room
3483 )))
3484 end
3485 end -- for each exit
3486end
3487
3488
3489function room_add_exit(room, uid)
3490-- gui function
3491 local available = {
3492 n = "North",
3493 s = "South",
3494 e = "East",
3495 w = "West",
3496 u = "Up",
3497 d = "Down",
3498 ne = "Northeast",
3499 sw = "Southwest",
3500 nw = "Northwest",
3501 se = "Southeast",
3502 tprt = "Teleport",
3503 prtl = "Portal",
3504 }
3505
3506 -- remove existing exits
3507 for k in pairs(room.exits) do
3508 available[k] = nil
3509 end
3510
3511 if next(available) == nil then
3512 utils.msgbox("All exits already used.", "No free exits!", "ok", "!", 1)
3513 return
3514 end -- not known
3515
3516 local chosen_exit = utils.listbox("Choose exit to add", "Exits ...", available)
3517 if (not chosen_exit) then
3518 return
3519 end
3520
3521 exit_destination = utils.inputbox("Enter destination room id for " .. available[chosen_exit], room.name, "")
3522
3523 if (not exit_destination) then
3524 return
3525 end -- cancelled
3526
3527 dbcheck(db:execute(string.format(
3528 "INSERT INTO exits(dir, fromuid, touid, date_added) VALUES(%s, %s, %s, DATETIME('NOW'));",
3529 fixsql(chosen_exit), -- direction (eg. "n")
3530 fixsql(uid), -- from current room
3531 fixsql(exit_destination) -- destination room
3532 )))
3533
3534 if (config2.show_database_mods) then
3535 mapper.mapprint("Added exit", available[chosen_exit], "from room", uid, "to room", exit_destination, "to database.")
3536 end
3537
3538 -- update in-memory table
3539 rooms[uid].exits[chosen_exit] = exit_destination
3540
3541 mapper.draw(current_room)
3542end
3543
3544
3545
3546-- -----------
3547-- deletions
3548-- -----------
3549
3550-----------------
3551-- delete rooms
3552-----------------
3553
3554function map_del_room(id)
3555 local room = load_room_from_database(id)
3556
3557 if (room) then -- room is in the map
3558
3559 if (count_exits(room.exits) == 0) then -- the room has no "from" links
3560 db:exec("BEGIN TRANSACTION;")
3561
3562 del_room_from_database(id)
3563
3564 local notes = load_notes_from_database(uid)
3565 if (notes) then
3566 del_bookmark_from_database(id)
3567 end
3568
3569 local tags = load_tags_from_database(uid)
3570 if (tags) then
3571 del_tags_from_database(id)
3572 end
3573
3574 db:exec("COMMIT;")
3575
3576 -- update in-memory table
3577 if (rooms[id]) then
3578 rooms[id] = nil
3579 end
3580
3581 mapper.draw(current_room)
3582
3583 else
3584 mapper.mapprint("Delete exits from room", id, "to other rooms first.")
3585 end
3586
3587 else
3588 mapper.mapprint("The room", id, "isn't in the map.")
3589 end
3590end
3591
3592
3593function count_exits(exits)
3594 local shortdir = {"n", "ne", "e", "se", "s", "sw", "w", "nw", "u", "d", "none"}
3595 local i, res
3596
3597 res = 0
3598
3599 for i = 1, #shortdir do
3600 if (exits[shortdir[i]]) then
3601 res = res + 1
3602 end
3603 end
3604
3605 return res
3606end
3607
3608
3609function del_room_from_database(uid)
3610 assert(uid, "No UID supplied to del_room_from_database")
3611
3612 dbcheck(db:execute(string.format(
3613 "DELETE FROM rooms WHERE uid = %s;",
3614 fixsql(uid)
3615 )))
3616
3617 dbcheck(db:execute(string.format(
3618 "DELETE FROM rooms_lookup WHERE uid = %s;",
3619 fixsql(uid)
3620 )))
3621
3622 if (config2.show_database_mods) then
3623 mapper.mapprint("Deleted room", uid, "from database")
3624 end
3625end
3626
3627
3628
3629---------------------
3630-- delete bookmarks
3631---------------------
3632
3633function map_del_bookmark(id)
3634 if (compatibility) then
3635 ColourNote("tomato", "black", "GMCP Mapper: I can't edit bookmarks in compatibility mode. Please upgrade your database.")
3636
3637 else
3638 if (id == "") then
3639 id = uid -- current room is default
3640 end
3641
3642 local notes = load_notes_from_database(id)
3643
3644 if (notes) then -- room is in the map
3645 db:exec("BEGIN TRANSACTION;")
3646
3647 del_bookmark_from_database(id)
3648
3649 db:exec("COMMIT;")
3650
3651 -- update in-memory table
3652 if (rooms[id]) then
3653 rooms[id].notes = ""
3654 end
3655
3656 mapper.mapprint("Bookmark for room", id, "deleted.")
3657
3658 else
3659 mapper.mapprint("The room", id, "doesn't have notes, or isn't mapped.")
3660 end
3661 end
3662end
3663
3664
3665function del_bookmark_from_database(uid)
3666 dbcheck(db:execute(string.format(
3667 "DELETE FROM bookmarks WHERE uid = %s;",
3668 fixsql(uid)
3669 )))
3670end
3671
3672
3673
3674----------------
3675-- delete tags
3676----------------
3677
3678function del_tags_from_database(uid)
3679 dbcheck(db:execute(string.format(
3680 "DELETE FROM player_tags WHERE uid = %s;",
3681 fixsql(uid)
3682 )))
3683end
3684
3685
3686
3687-----------------
3688-- delete exits
3689-----------------
3690
3691function map_del_exits(fromid)
3692 if (fromid == "") then
3693 fromid = uid -- current room is default
3694 end
3695
3696 local room = load_room_from_database(fromid)
3697
3698 if (room) then -- room fromid is in the map
3699 db:exec("BEGIN TRANSACTION;")
3700
3701 del_exits_from_database(fromid)
3702
3703 db:exec("COMMIT;")
3704
3705 -- update in-memory table
3706 if (rooms[fromid]) then
3707 rooms[fromid].exits = {}
3708 end
3709
3710 else
3711 mapper.mapprint("The room", fromid, "isn't in the map.")
3712 end
3713end
3714
3715
3716function map_del_exit(dir, fromid)
3717 if (fromid == "") then
3718 fromid = uid -- current room is default
3719 end
3720
3721 local room = load_room_from_database(fromid)
3722
3723 if (room) then -- room fromid is in the map
3724 if ((is_valid_direction(dir)) or (dir == "none")) then
3725 db:exec("BEGIN TRANSACTION;")
3726
3727 del_exit_from_database(dir, fromid)
3728
3729 db:exec("COMMIT;")
3730
3731 -- update in-memory table
3732 if (rooms[fromid]) then
3733 rooms[fromid].exits[dir] = nil
3734 end
3735
3736 mapper.draw(current_room)
3737
3738 else
3739 mapper.mapprint("You must provide a valid direction (n, ne, etc.)")
3740 end
3741
3742 else
3743 mapper.mapprint("The room", fromid, "isn't in the map.")
3744 end
3745end
3746
3747
3748function del_exits_from_database(uid)
3749 assert(uid, "No UID supplied to del_room_from_database")
3750
3751 dbcheck(db:execute(string.format(
3752 "DELETE FROM exits WHERE fromuid = %s;",
3753 fixsql(uid) -- fromuid
3754 )))
3755
3756 if (config2.show_database_mods) then
3757 mapper.mapprint("Deleted all exits from room", uid, "from database")
3758 end
3759end
3760
3761
3762function del_exit_from_database(dir, fromuid)
3763 assert(dir, "No direction supplied to add_exit_to_database")
3764 assert(fromuid, "No fromUID supplied to add_exit_to_database")
3765
3766 dbcheck(db:execute(string.format(
3767 "DELETE FROM exits WHERE dir = %s AND fromuid = %s;",
3768 fixsql(dir), -- dir
3769 fixsql(fromuid) -- fromuid
3770 )))
3771
3772 if (config2.show_database_mods) then
3773 mapper.mapprint("Deleted exit from database,", dir, "from", fromuid)
3774 end
3775end
3776
3777
3778function room_delete_exit(room, uid)
3779-- gui function
3780 local available = {
3781 n = "North",
3782 s = "South",
3783 e = "East",
3784 w = "West",
3785 u = "Up",
3786 d = "Down",
3787 ne = "Northeast",
3788 sw = "Southwest",
3789 nw = "Northwest",
3790 se = "Southeast",
3791 tprt = "Teleport",
3792 prtl = "Portal",
3793 }
3794
3795 -- remove non-existent exits
3796 for k in pairs(available) do
3797 if room.exits[k] then
3798 available[k] = available[k] .. " --> " .. room.exits[k]
3799 else
3800 available[k] = nil
3801 end -- if not a room exit
3802 end
3803
3804 if (next(available) == nil) then
3805 utils.msgbox("There are no exits from this room.", "No exits!", "ok", "!", 1)
3806 return
3807 end -- not known
3808
3809 local chosen_exit = utils.listbox("Choose exit to delete", "Exits ...", available)
3810 if (not chosen_exit) then
3811 return
3812 end
3813
3814 dbcheck(db:execute(string.format(
3815 "DELETE FROM exits WHERE dir = %s AND fromuid = %s;",
3816 fixsql(chosen_exit), -- direction (eg. "n")
3817 fixsql(uid) -- from current room
3818 )))
3819
3820 if (config2.show_database_mods) then
3821 mapper.mapprint("Deleted exit", available[chosen_exit], "from room", uid, "from database.")
3822 end
3823
3824 -- update in-memory table
3825 rooms[uid].exits[chosen_exit] = nil
3826
3827 mapper.draw(current_room)
3828end
3829
3830
3831
3832-- ---------------
3833-- modifications
3834-- ---------------
3835
3836-----------------
3837-- modify rooms
3838-----------------
3839
3840function update_room(uid)
3841 db:exec("BEGIN TRANSACTION;")
3842
3843 local oldarea, zone, oldname, name, oldterrain, terrain, oldterraininfo, terraininfo, oldflags, flags, cflags
3844
3845 if (not uid) then
3846 uid = gmcpval("num")
3847 end
3848
3849 zone = gmcpval("zone")
3850
3851 oldarea = rooms[uid].area -- if area has changed, then update/add it
3852 if (oldarea ~= zone) then
3853 room_update_area(uid, zone)
3854 end
3855
3856 name = gmcpval("name")
3857 oldname = rooms[uid].name -- if name has changed, then update/add it,
3858 if (oldname ~= roomname) then
3859 room_update_name(uid, roomname)
3860 end
3861
3862 -- fix exits, in case some of them are missing
3863 fix_exits(zone, uid, exits_str)
3864
3865 terrain = gmcpval("terrain")
3866 oldterrain = rooms[uid].terrain -- if terrain has changed, then update/add it
3867 if (oldterrain ~= terrain) then
3868 room_update_terrain(uid, terrain)
3869 end
3870
3871 terraininfo = gmcpval("terraininfo")
3872 oldterraininfo = rooms[uid].terraininfo -- if terraininfo has changed, then update/add it
3873 if (oldterraininfo ~= terraininfo) then
3874 room_update_terraininfo(uid, terraininfo)
3875 end
3876
3877 flags = gmcpval("flags")
3878 if (flags == "_empty") then
3879 flags = ""
3880 end
3881 oldflags = (rooms[uid].flags or "") -- if flags have changed, then update/add them,
3882 cflags = flags
3883 if (zone == "Tellerium") then
3884 cflags = remove_anti_magic(flags)
3885 oldflags = remove_anti_magic(flags)
3886 end
3887 if (oldflags ~= cflags) then
3888 room_update_flags(uid, flags)
3889 end
3890
3891 db:exec("COMMIT;")
3892
3893 mapper.draw(current_room)
3894end
3895
3896
3897function remove_anti_magic(flags)
3898 flags = flags or ""
3899 flags = string.gsub(flags, "anti%-magic, ", "")
3900 flags = string.gsub(flags, ", anti%-magic", "")
3901 flags = string.gsub(flags, "anti%-magic", "")
3902 return flags
3903end
3904
3905
3906
3907----------------
3908-- modify area
3909----------------
3910
3911function room_update_area(uid, zone)
3912 dbcheck(db:execute(string.format(
3913 "UPDATE rooms SET area = %s WHERE uid = %s;",
3914 fixsql(zone),
3915 fixsql(uid)
3916 )))
3917
3918 if (not compatibility) then
3919 dbcheck(db:execute(string.format(
3920 "UPDATE rooms_lookup SET area = %s WHERE uid = %s;",
3921 fixsql(zone),
3922 fixsql(uid)
3923 )))
3924 end
3925
3926 if (config2.show_database_mods) then
3927 mapper.mapprint("Room", uid, "area updated")
3928 end
3929
3930 if (rooms[id]) then
3931 rooms[uid].area = zone
3932 end
3933end -- room_update_area
3934
3935
3936
3937----------------
3938-- modify name
3939----------------
3940
3941function room_update_name(uid, name)
3942 dbcheck(db:execute(string.format(
3943 "UPDATE rooms SET name = %s WHERE uid = %s;",
3944 fixsql(name),
3945 fixsql(uid)
3946 )))
3947
3948 dbcheck(db:execute(string.format(
3949 "UPDATE rooms_lookup SET name = %s WHERE uid = %s;",
3950 fixsql(name),
3951 fixsql(uid)
3952 )))
3953
3954 if (config2.show_database_mods) then
3955 mapper.mapprint("Room", uid, "name updated")
3956 end
3957
3958 if (rooms[id]) then
3959 rooms[uid].name = name
3960 end
3961end
3962
3963
3964
3965---------------------------------
3966-- modify terrain / terraintype
3967---------------------------------
3968
3969function room_update_terrain(uid, terrain)
3970 dbcheck(db:execute(string.format(
3971 "UPDATE rooms SET terrain = %s WHERE uid = %s;",
3972 fixsql(terrain),
3973 fixsql(uid)
3974 )))
3975
3976 if (config2.show_database_mods) then
3977 mapper.mapprint("Room", uid, "terrain updated")
3978 end
3979
3980 if (rooms[id]) then
3981 rooms[uid].terrain = terrain
3982 end
3983end
3984
3985
3986function room_update_terraininfo(uid, terraininfo)
3987 dbcheck(db:execute(string.format(
3988 "UPDATE rooms SET terraininfo = %s WHERE uid = %s;",
3989 fixsql(terraininfo),
3990 fixsql(uid)
3991 )))
3992
3993 if (config2.show_database_mods) then
3994 mapper.mapprint("Room", uid, "terraininfo updated")
3995 end
3996
3997 if (rooms[id]) then
3998 rooms[uid].terraininfo = terraininfo
3999 end
4000end
4001
4002
4003
4004-----------------
4005-- modify flags
4006-----------------
4007
4008function room_update_flags(uid, flags)
4009 local use_column = "flags"
4010 if (compatibility) then
4011 use_column = "description"
4012 end
4013
4014 dbcheck(db:execute(string.format(
4015 "UPDATE rooms SET %s = %s WHERE uid = %s;",
4016 use_column,
4017 fixsql(flags),
4018 fixsql(uid)
4019 )))
4020
4021 if (compatibility) then
4022 dbcheck(db:execute(string.format(
4023 "UPDATE rooms_lookup SET description = %s WHERE uid = %s;",
4024 fixsql(flags),
4025 fixsql(uid)
4026 )))
4027 end
4028
4029 if (config2.show_database_mods) then
4030 mapper.mapprint("Room", uid, "flags updated")
4031 end
4032
4033 if (rooms[uid]) then
4034 rooms[uid].flags = flags
4035 end
4036end
4037
4038
4039
4040---------------------
4041-- modify bookmarks
4042---------------------
4043
4044function update_bookmark(uid, notes)
4045 dbcheck(db:execute(string.format(
4046 "UPDATE bookmarks SET notes = %s WHERE uid = %s;",
4047 fixsql(notes),
4048 fixsql(uid)
4049 )))
4050end
4051
4052
4053
4054----------------
4055-- modify tags
4056----------------
4057
4058function map_toggle_tag(id, tag)
4059 if (compatibility) then
4060 ColourNote("tomato", "black", "GMCP Mapper: I can't tag rooms in compatibility mode. Please upgrade your database.")
4061
4062 else
4063 if (id == "") then
4064 id = uid -- current room is default
4065 end
4066
4067 local room = rooms[id]
4068
4069 if (not room) then
4070 room = load_room_from_database(uid)
4071 end
4072
4073 if (not room) then
4074 mapper.mapprint("The room", id, "isn't in the map.")
4075
4076 else
4077 room_toggle_tag(room, id, tag)
4078 end
4079 end
4080end
4081
4082
4083function room_toggle_tag(room, uid, tag)
4084 if (compatibility) then
4085 ColourNote("tomato", "black", "GMCP Mapper: I can't tag rooms in compatibility mode. Please upgrade your database.")
4086
4087 else
4088 if (has_tag(rooms[uid].tags, tag)) then
4089 rooms[uid].tags = del_a_tag(rooms[uid].tags, tag)
4090 else
4091 rooms[uid].tags = add_a_tag(rooms[uid].tags, tag)
4092 end
4093
4094 db:exec("BEGIN TRANSACTION;")
4095
4096 local tags = room.tags or ""
4097 if (Trim(tags) == "") then
4098 tags = nil
4099 end
4100
4101 if (tags) then
4102 if (rooms[uid].tags) then
4103 save_tags_to_database(uid, rooms[uid].tags)
4104 end
4105
4106 else
4107 if (rooms[uid].tags) then
4108 update_tags(uid, rooms[uid].tags)
4109 else
4110 del_tags_from_database(uid)
4111 end
4112 end
4113
4114 db:exec("COMMIT;")
4115
4116 if (has_flag(rooms[uid].tags, tag)) then
4117 mapper.mapprint("Room", uid, "tagged as", tag)
4118 else
4119 mapper.mapprint("Room", uid, "no longer tagged as", tag)
4120 end
4121
4122 mapper.draw(current_room)
4123 end
4124end
4125
4126
4127function add_a_tag(tags, tag)
4128 if (not tags) or (Trim(tags) == "") then
4129 tags = tag
4130 else
4131 tags = tags .. ", " .. tag
4132 end
4133
4134 return tags
4135end
4136
4137
4138function del_a_tag(tags, tag)
4139 if (tags) and (has_tag(tags, tag)) then
4140 tags = string.gsub(tags, escaped_str(tag) .. ", ", "")
4141 tags = string.gsub(tags, ", " .. escaped_str(tag) .. "$", "")
4142 tags = string.gsub(tags, escaped_str(tag), "")
4143
4144 tags = Trim(tags)
4145
4146 if (tags == "") then
4147 tags = nil
4148 end
4149 end
4150
4151 return tags
4152end
4153
4154
4155function update_tags(uid, tags)
4156 dbcheck(db:execute(string.format(
4157 "UPDATE player_tags SET tags = %s WHERE uid = %s;",
4158 fixsql(tags),
4159 fixsql(uid)
4160 )))
4161end
4162
4163
4164
4165-----------------
4166-- modify exits
4167-----------------
4168
4169function fix_exits(zone, uid, exits)
4170 local dest, aux
4171
4172 for dir in string.gmatch(exits, "%a+") do
4173 dest = gmcpval("exits." .. dir)
4174
4175 if (dest) and (dest ~= "none") and (dest ~= "-99")
4176 and (not is_volatile(uid)) and (not is_volatile(dest)) then
4177
4178 if (dest ~= rooms[uid].exits[dir]) then -- exit changed, update it
4179
4180 dbcheck(db:execute(string.format(
4181 "INSERT INTO exits(dir, fromuid, touid, date_added) VALUES(%s, %s, %s, DATETIME('NOW'));",
4182 fixsql(dir), -- direction (eg. "n")
4183 fixsql(uid), -- from current room
4184 fixsql(dest) -- destination room
4185 )))
4186
4187 -- update in-memory table
4188 rooms[uid].exits[dir] = dest
4189
4190 if (config2.show_database_mods) then
4191 mapper.mapprint("Room", uid, "-", dir, "exit updated")
4192 end
4193 end
4194 end
4195
4196 end -- for each exit
4197end
4198
4199
4200function room_change_exit(room, uid)
4201-- gui function
4202 local available = {
4203 n = "North",
4204 s = "South",
4205 e = "East",
4206 w = "West",
4207 u = "Up",
4208 d = "Down",
4209 ne = "Northeast",
4210 sw = "Southwest",
4211 nw = "Northwest",
4212 se = "Southeast",
4213 tprt = "Teleport",
4214 prtl = "Portal",
4215 } -- end of available
4216
4217 -- remove non-existent exits
4218 for k in pairs(available) do
4219 if room.exits[k] then
4220 available[k] = available[k] .. " --> " .. room.exits[k]
4221 else
4222 available[k] = nil
4223 end -- if not a room exit
4224 end
4225
4226 if (next(available) == nil) then
4227 utils.msgbox("There are no exits from this room.", "No exits!", "ok", "!", 1)
4228 return
4229 end -- not known
4230
4231 local chosen_exit = utils.listbox("Choose exit to change destination of:", "Exits ...", available)
4232 if not chosen_exit then
4233 return
4234 end
4235
4236 exit_destination = utils.inputbox("Enter destination room id for " .. available[chosen_exit], room.name, "")
4237
4238 if not exit_destination then
4239 return
4240 end -- cancelled
4241
4242 dbcheck(db:execute(string.format(
4243 "UPDATE exits SET touid = %s WHERE dir = %s AND fromuid = %s;",
4244 fixsql(exit_destination),
4245 fixsql(chosen_exit), -- direction (eg. "n")
4246 fixsql(uid) -- from current room
4247 )))
4248
4249 if (config2.show_database_mods) then
4250 mapper.mapprint("Modified exit", available[chosen_exit], "from room", uid, "to be to room", exit_destination, "in database.")
4251 end
4252
4253 -- update in-memory table
4254 rooms[uid].exits[chosen_exit] = exit_destination
4255 mapper.draw(current_room)
4256end
4257
4258
4259
4260-- ---------------
4261-- special areas
4262-- ---------------
4263
4264function toggle_wilds_mapping(status)
4265 config2.do_map_wilds = do_toggle(config2.do_map_wilds, status)
4266
4267 save_config2()
4268
4269 if (config2.do_map_wilds) then
4270 Note("-- MM_GMCP_Mapper: wilds mapping ON --")
4271
4272 else
4273 Note("-- MM_GMCP_Mapper: wilds mapping OFF --")
4274 end
4275
4276-- mapper.draw(current_room)
4277end
4278
4279
4280
4281-- -------------
4282-- maintenance
4283-- -------------
4284
4285--------------
4286-- room info
4287--------------
4288
4289function show_room_info(id)
4290 if (id == "") then
4291 id = uid -- current room is default
4292 end
4293
4294 local room = load_room_from_database(id)
4295
4296 if (room) then -- room is in the map
4297 Tell("id: ")
4298 ColourNote(fontcol, bgcol, id)
4299 Tell("name: ")
4300 ColourNote(fontcol, bgcol, room.name)
4301 Tell("zone: ")
4302 ColourNote(fontcol, bgcol, room.area)
4303
4304 if (room.terrain) then
4305 Tell("terrain: ")
4306 ColourNote(fontcol, bgcol, room.terrain)
4307 end
4308
4309 if (room.terraininfo) then
4310 Tell("terraininfo: ")
4311 ColourNote(fontcol, bgcol, room.terraininfo)
4312 end
4313
4314 Tell("flags: ")
4315 ColourNote(fontcol, bgcol, room.flags or "-")
4316
4317 room.tags = load_tags_from_database(id)
4318 Tell("tags: ")
4319 ColourNote(fontcol, bgcol, room.tags or "-")
4320
4321 room.notes = load_notes_from_database(id)
4322 if (room.notes) then
4323 Tell("bookmarks: ")
4324 ColourNote(fontcol, bgcol, room.notes)
4325 end
4326
4327 if (room.exits) then
4328 Tell("exits: ")
4329 ColourNote(fontcol, bgcol, serialize.save_simple(room.exits))
4330 end
4331
4332 else
4333 mapper.mapprint("The room", id, "isn't in the map.")
4334 end
4335end
4336
4337
4338function export_rooms(name)
4339-- name must be an exact room match
4340
4341 local sname = string.upper(name)
4342 local t = {}
4343
4344 for row in db:nrows(string.format('SELECT * FROM rooms WHERE UPPER(name) = "%s"', sname)) do
4345 t[#t + 1] = row.uid
4346 end -- finding rooms
4347
4348 for i = 1, #t do
4349 do_export_room(t[i])
4350 end
4351end
4352
4353
4354function export_area(name)
4355 local sname = string.upper(name)
4356 local t = {}
4357
4358 for row in db:nrows(string.format('SELECT * FROM rooms WHERE UPPER(area) = "%s"', sname)) do
4359 t[#t + 1] = row.uid
4360 end -- finding rooms
4361
4362 for i = 1, #t do
4363 do_export_room(t[i])
4364 end
4365end
4366
4367
4368function do_export_room(num)
4369 local room = load_room_from_database(num)
4370
4371 if (room) then
4372 AppendToNotepad("exported rooms", "mapper addroom " .. num .. " n:" .. room.name .. " a:" .. room.area .. " f:" .. (room.flags or " ") .. " t:" .. (room.terrain or " ") .. " ti:" .. (room.terraininfo or " ") .. "\r\n")
4373
4374 if (Trim(room.notes or "") ~= "") then
4375 AppendToNotepad("exported rooms", "mapper addbm " .. num .. " b:" .. room.notes .."\r\n")
4376 end
4377
4378 if (has_tag(room.tags, "dt")) then
4379 AppendToNotepad("exported rooms", "mapper dt " .. num .."\r\n")
4380 end
4381
4382 if (has_tag(room.tags, "no-speed")) then
4383 AppendToNotepad("exported rooms", "mapper nospeed " .. num .."\r\n")
4384 end
4385
4386 if (has_tag(room.tags, "shop")) then
4387 AppendToNotepad("exported rooms", "mapper shop " .. num .."\r\n")
4388 end
4389
4390 if (has_tag(room.tags, "trainer")) then
4391 AppendToNotepad("exported rooms", "mapper trainer " .. num .."\r\n")
4392 end
4393
4394 for dir, touid in pairs(room.exits) do
4395 AppendToNotepad("exported rooms", "mapper addexit " .. dir .. " f:" .. num .. " t:" .. touid .. "\r\n")
4396 end
4397 end
4398end
4399
4400
4401
4402----------------
4403-- purge stuff
4404----------------
4405
4406function purge_entire_area(name)
4407 local arooms = {}
4408 local aname = fixsql(string.upper(name))
4409
4410 -- make list of stuff to delete
4411 for row in db:nrows(string.format("SELECT uid FROM rooms WHERE UPPER(area) = %s", aname)) do
4412 arooms[#arooms + 1] = row.uid
4413 end -- finding rooms
4414
4415 purge_stuff(arooms, name, false)
4416end
4417
4418
4419function purge_wilds(name)
4420 local prooms = {}
4421 local pname = fixsql(string.upper(name))
4422
4423 if (is_vmap(name)) then
4424 -- make list of stuff to delete
4425 for row in db:nrows(string.format("SELECT uid, name, terrain FROM rooms WHERE UPPER(area) = %s", pname)) do
4426 if (not is_road(row.terrain)) or (is_cave(row.name)) then
4427 prooms[#prooms + 1] = row.uid
4428 end
4429 end -- finding rooms
4430
4431 purge_stuff(prooms, name, false)
4432
4433 else
4434 mapper.mapprint("'" .. name .. "' is not a valid plane name.")
4435 end
4436end
4437
4438
4439function purge_pursuer()
4440 local prooms = {}
4441 local pname = "A Dizzying Array"
4442
4443 -- make lists of stuff to delete
4444 for row in db:nrows(string.format("SELECT uid FROM rooms WHERE name = '%s'", pname)) do
4445 prooms[#prooms + 1] = row.uid
4446 end -- finding rooms
4447
4448 purge_bookmarks(prooms, pname)
4449 purge_stuff(prooms, pname, true)
4450end
4451
4452
4453function purge_sandbox()
4454 local srooms = {}
4455 local sarea = "The Housing Sandbox"
4456
4457 -- make list of stuff to delete
4458 for row in db:nrows(string.format("SELECT uid FROM rooms WHERE area = '%s'", sarea)) do
4459 srooms[#srooms + 1] = row.uid
4460 end -- finding rooms
4461
4462 purge_stuff(srooms, sarea, false)
4463end
4464
4465
4466function purge_molehill()
4467 local mrooms = {}
4468 local marea = "A Labyrinthine Molehill"
4469 local mnotes = {}
4470
4471 -- make lists of stuff to delete
4472 for row in db:nrows(string.format("SELECT uid FROM rooms WHERE area = '%s'", marea)) do
4473 mrooms[#mrooms + 1] = row.uid
4474
4475 if (row.notes) and (row.notes ~= "NULL") and (row.notes ~= "") then
4476 mnotes[#mnotes + 1] = row.uid
4477 end
4478 end -- finding rooms
4479
4480 purge_bookmarks(mnotes, marea)
4481 purge_stuff(mrooms, marea, true)
4482end
4483
4484
4485function purge_bookmarks(t, name)
4486 if (#t > 0) then
4487 db:exec("BEGIN TRANSACTION;")
4488
4489 mapper.mapprint("Deleting " .. name .. " bookmarks...")
4490 for i = 1, #t do
4491 SetStatus("Erasing bookmark for room " .. t[i] .. "...")
4492 map_del_bookmark(t[i])
4493
4494 -- update in-memory table
4495 if (rooms[t[i]]) then
4496 rooms[t[i]].notes = nil
4497 end
4498 end
4499
4500 db:exec("COMMIT;")
4501
4502 mapper.mapprint("Done.")
4503 SetStatus("Ready")
4504
4505 else
4506 mapper.mapprint("No bookmarks found for '" .. name .. "'")
4507 end
4508end
4509
4510
4511function purge_list(list, name, unlink)
4512 local t = utils.split(list, " ")
4513
4514 purge_stuff(t, name, unlink)
4515end
4516
4517
4518function purge_stuff(t, name, unlink)
4519 if (#t > 0) then
4520 db:exec("BEGIN TRANSACTION;")
4521
4522 if (unlink) then
4523 mapper.mapprint("Unlinking " .. name .. "...")
4524 else
4525 mapper.mapprint("Purging " .. name .. "...")
4526 end
4527
4528 for i = 1, #t do
4529 if (unlink) then
4530 unlink_room(t[i])
4531 else
4532 nuke_room(t[i])
4533 end
4534 end
4535
4536 db:exec("COMMIT;")
4537
4538 mapper.mapprint("Done.")
4539 SetStatus("Ready")
4540
4541 mapper.draw(current_room)
4542
4543 else
4544 mapper.mapprint("No rooms found for '" .. name .. "'")
4545 end
4546end
4547
4548
4549function unlink_room(uid)
4550 SetStatus("Unlinking room " .. uid .. "...")
4551 del_exits_from_database(uid)
4552
4553 -- update in-memory table
4554 if (rooms[uid]) then
4555 rooms[uid].exits = {}
4556 end
4557end
4558
4559
4560function nuke_room(uid)
4561 SetStatus("Erasing room " .. uid .. "...")
4562 del_exits_from_database(uid)
4563 del_room_from_database(uid)
4564
4565 local notes = load_notes_from_database(uid)
4566 if (notes) then
4567 del_bookmark_from_database(uid)
4568 end
4569
4570 local tags = load_tags_from_database(uid)
4571 if (tags) then
4572 del_tags_from_database(uid)
4573 end
4574
4575 -- update in-memory table
4576 rooms[uid] = nil
4577end
4578
4579
4580
4581------------------
4582-- privacy stuff
4583------------------
4584
4585function purge_clanhalls()
4586 local row
4587 local crooms = {}
4588 local careas = "% Clan Hall"
4589
4590 db:exec("BEGIN TRANSACTION;")
4591
4592 -- make list of stuff to delete
4593 for row in db:nrows(string.format("SELECT uid, area FROM rooms WHERE area like '%s'", careas)) do
4594 if (string.find(row.area, "Old ") ~= 1)
4595 and (string.find(row.area, "The Old ") ~= 1) then
4596 crooms[#crooms + 1] = row.uid
4597 end
4598 end -- finding rooms
4599
4600 mapper.mapprint("Purging clan halls data...")
4601 for i = 1, #crooms do
4602 SetStatus("Erasing room " .. crooms[i] .. "...")
4603
4604 del_exits_from_database(crooms[i])
4605
4606 del_room_from_database(crooms[i])
4607
4608 -- update in-memory table
4609 rooms[crooms[i]] = nil
4610 end
4611
4612 db:exec("COMMIT;")
4613
4614 mapper.mapprint("Done.")
4615 SetStatus("Ready")
4616
4617 mapper.draw(current_room)
4618end
4619
4620
4621function purge_player_homes()
4622 local row
4623 local hrooms = {}
4624 local hareas = "Player Homes %"
4625
4626 db:exec("BEGIN TRANSACTION;")
4627
4628 -- make list of stuff to delete
4629 for row in db:nrows(string.format("SELECT uid, area FROM rooms WHERE area like '%s'", hareas)) do
4630 if (uid ~= "25022646") then -- The Pirate's Cove Housing District
4631 hrooms[#hrooms + 1] = row.uid
4632 end
4633 end -- finding rooms
4634
4635 mapper.mapprint("Purging player homes data...")
4636 for i = 1, #hrooms do
4637 SetStatus("Erasing room " .. hrooms[i] .. "...")
4638
4639 del_exits_from_database(hrooms[i])
4640
4641 del_room_from_database(hrooms[i])
4642
4643 -- update in-memory table
4644 rooms[hrooms[i]] = nil
4645 end
4646
4647 db:exec("COMMIT;")
4648
4649 mapper.mapprint("Done.")
4650 SetStatus("Ready")
4651
4652 mapper.draw(current_room)
4653end
4654
4655
4656function purge_notes()
4657 local row
4658 local brooms = {}
4659
4660 db:exec("BEGIN TRANSACTION;")
4661
4662 -- make lists of stuff to delete
4663 for row in db:nrows(string.format("SELECT uid, notes, area FROM rooms")) do
4664 if (not is_vmap())
4665 and (row.notes) then
4666 brooms[#brooms + 1] = row.uid
4667 end
4668 end -- finding rooms
4669
4670 -- delete bookmarks
4671 mapper.mapprint("Deleting non-vmap bookmarks...")
4672 for i = 1, #brooms do
4673 SetStatus("Erasing bookmark for room " .. brooms[i] .. "...")
4674 map_del_bookmark(brooms[i])
4675 end
4676
4677 db:exec("COMMIT;")
4678
4679 mapper.mapprint("Done.")
4680 SetStatus("Ready")
4681
4682 mapper.draw(current_room)
4683end
4684
4685
4686
4687------------------
4688-- rebuild stuff
4689------------------
4690
4691function rebuild_lookup()
4692 db:exec("BEGIN TRANSACTION;")
4693
4694 mapper.mapprint("Rebuilding rooms_lookup table...")
4695
4696 -- delete all rows from rooms_lookup
4697 dbcheck(db:execute(string.format(
4698 "DELETE FROM rooms_lookup;"
4699 )))
4700
4701 local use_column = "area"
4702 if (compatibility) then
4703 use_column = "description"
4704 end
4705
4706 for row in db:nrows(string.format("SELECT uid, name, %s FROM rooms", use_column)) do
4707 SetStatus("Recreating rooms_lookup entry for room " .. uid)
4708
4709 local use_field = row.area
4710 if (compatibility) then
4711 use_field = row.description
4712 end
4713
4714 dbcheck(db:execute(string.format(
4715 "INSERT INTO rooms_lookup(uid, name, %s) VALUES(%s, %s, %s);",
4716 use_column,
4717 fixsql(row.uid),
4718 fixsql(row.name),
4719 fixsql(use_field)
4720 )))
4721 end -- finding rooms
4722
4723 db:exec("COMMIT;")
4724 SetStatus("Ready")
4725
4726 mapper.mapprint("Done.")
4727end
4728
4729
4730function recreate_database(cmd)
4731 -- open databases on disk
4732 if (cmd == "upgrade") and (compatibility) then
4733 dbnew = assert(sqlite3.open(GetInfo(66) .. "mm_mapper.db"))
4734 else
4735 dbnew = assert(sqlite3.open(GetInfo(66) .. "mm_mapper_new.db"))
4736 end
4737
4738 -- create rooms table
4739 create_tables_new(dbnew)
4740
4741 dbnew:exec("BEGIN TRANSACTION;")
4742
4743 -- copy rooms from "old" table
4744 local room
4745
4746 for row in db:nrows(string.format("SELECT * FROM rooms")) do
4747 SetStatus("Copying room " .. row.uid .. " to the new database...")
4748
4749 room = do_load_room(row.uid)
4750 room.uid = row.uid
4751
4752 if (compatibility) then
4753 room.flags = fix_flag(room.flags, row.safe, "safe")
4754 room.flags = fix_flag(room.flags, row.lpk, "player-kill-lawful")
4755 room.flags = fix_flag(room.flags, row.npk, "player-kill-neutral")
4756 room.flags = fix_flag(room.flags, row.cpk, "player-kill-chaotic")
4757 end
4758
4759 dbcheck(dbnew:execute(string.format(
4760 "INSERT INTO rooms(uid, name, flags, area, terrain, terraininfo, date_added) VALUES(%s, %s, %s, %s, %s, %s, %s);",
4761 fixsql(room.uid),
4762 fixsql(room.name),
4763 fixsql(room.flags),
4764 fixsql(room.area),
4765 fixsql(room.terrain),
4766 fixsql(room.terraininfo),
4767 fixsql(room.date_added)
4768 )))
4769
4770 if (room.notes) and (room.notes ~= "") then
4771 dbcheck(dbnew:execute(string.format(
4772 "INSERT INTO bookmarks(uid, notes) VALUES(%s, %s);",
4773 fixsql(room.uid),
4774 fixsql(row.notes)
4775 )))
4776 end
4777
4778 if (room.tags) and (room.tags ~= "") then
4779 dbcheck(dbnew:execute(string.format(
4780 "INSERT INTO player_tags(uid, tags) VALUES(%s, %s);",
4781 fixsql(room.uid),
4782 fixsql(room.tags)
4783 )))
4784 end
4785 end
4786
4787 -- copy exits from "old" table
4788
4789 for row in db:nrows(string.format("SELECT * FROM exits")) do
4790 SetStatus("Copying exits from room " .. row.fromuid .. " to the new database...")
4791
4792 dbcheck(dbnew:execute(string.format(
4793 "INSERT INTO exits(dir, fromuid, touid, date_added) VALUES(%s, %s, %s, %s);",
4794 fixsql(row.dir),
4795 fixsql(row.fromuid),
4796 fixsql(row.touid),
4797 fixsql(row.date_added)
4798 )))
4799 end
4800
4801 SetStatus("Committing changes...")
4802
4803 dbnew:exec("COMMIT;")
4804
4805 SetStatus("Ready.")
4806
4807 if (cmd == "upgrade") and (compatibility) then
4808 ColourTell("white", "navy", "GMCP Mapper: your database has been upgraded to the new structure - ")
4809 ColourTell("lime", "navy", "reinstall this plugin")
4810 ColourNote("white", "navy", " to start using the new file.")
4811
4812 else
4813 ColourNote("white", "black", "GMCP Mapper: your database has been recreated as ")
4814 ColourTell("lime", "black", "mm_mapper_new.db")
4815 ColourNote("white", "black", " in your MUSHclient folder.")
4816 end
4817end
4818
4819
4820
4821-- ------
4822-- misc
4823-- ------
4824
4825------------------------
4826-- scripting functions
4827------------------------
4828
4829function speeding()
4830 return (not mapper.check_we_can_find())
4831end
4832
4833
4834function handled_door()
4835 return (config2.auto_open)
4836end
4837
4838
4839
4840------------------------
4841-- sapi / reader stuff
4842------------------------
4843
4844function detect_reader()
4845 local res = reader_plugin_present()
4846
4847 if (res) then
4848 config2.visible = false
4849 save_config2()
4850 end
4851
4852 return res
4853end
4854
4855
4856function reader_plugin_present()
4857 return is_plugin_present("MushReader", "925cdd0331023d9f0b8f05a7")
4858end
4859
4860
4861function sapi_plugin_present()
4862 return is_plugin_present("Sapi_speaker", "463242566069ebfd1b379ec1") or is_plugin_present("Text_To_Speech", "463242566069ebfd1b379ec1")
4863end
4864
4865
4866function sapi_say(text)
4867 if (sapi_present) then
4868 local res = CallPlugin("463242566069ebfd1b379ec1", "say", text)
4869 end
4870end
4871
4872
4873]]>
4874
4875</script>
4876
4877</muclient>