Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

1948 lines (1528 sloc) 51.056 kB
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE muclient [
<!ENTITY show_vnums "true" >
<!ENTITY show_timing "false" >
<!ENTITY show_completed "false" >
<!ENTITY show_database_mods "true" >
<!ENTITY show_other_areas "false" >
<!ENTITY show_area_exits "true" >
<!ENTITY show_up_down "false" >
<!ENTITY speedwalk_prefix "" >
]>
<muclient>
<plugin
name="ATCP_Mapper"
author="Nick Gammon"
id="a80b38e2f618fbda79a6440c"
language="Lua"
purpose="Draws map for ATCP MUDs"
date_written="2010-03-04"
date_modified="2010-11-26"
requires="4.51"
version="1.6"
save_state="y"
>
<description trim="y">
<![CDATA[
AUTOMATIC MAPPER ... by Nick Gammon
The window can be dragged to a new location by dragging the room name.
Your current room is always in the center with a bolder border.
LH-click on a room to speed-walk to it. RH-click on a room for options.
LH-click on the "*" button on the bottom-left corner to configure it.
** WHY DOES THE MAP CHANGE? **
The mapper draws from your room outwards - that is, it draws your room's exits
first, then the rooms leading from those rooms, and so on.
Eventually it finds an overlap, and draws a short "stub" line to indicate there
is a room there which there isn't space to draw. If you get closer to that
room the stub will disappear and the room(s) in question will be drawn.
ACTIONS
mapper help --> this help (or click the "?" button on the bottom right)
mapper zoom out --> zoom out (or use the mouse-wheel)
mapper zoom in --> zoom in (or use the mouse-wheel)
mapper hide --> hide map
mapper show --> show map
FINDING THINGS
mapper bookmarks --> show nearby rooms that you bookmarked
mapper find <text> --> full-text search (eg. shop OR baker)
mapper areas --> show path to nearby areas (zones)
mapper heal --> show nearby healers
mapper shop --> show nearby shops/banks etc.
mapper train --> show nearby trainers
mapper quest --> show nearby quest-givers
mapper where <room> --> show directions to a room
MOVING
mapper goto <room> --> walk to a room by its room number
mapper stop --> cancel any current speedwalk
mapper resume --> resume last speedwalk or hyperlinked speedwalk
]]>
</description>
</plugin>
<aliases>
<!-- zooming aliases -->
<alias
match="mapper zoom out"
enabled="y"
sequence="100"
omit_from_command_history="y"
omit_from_output="y"
script="mapper.zoom_out"
>
</alias>
<alias
match="mapper zoom in"
enabled="y"
sequence="100"
omit_from_command_history="y"
omit_from_output="y"
script="mapper.zoom_in"
>
</alias>
<!-- finding aliases -->
<alias
match="^mapper find ([\w* %d/&quot;]+)$"
enabled="y"
sequence="100"
script="map_find"
regexp="y"
>
</alias>
<alias
match="mapper areas"
enabled="y"
sequence="100"
script="map_areas"
>
</alias>
<alias
match="^mapper shops?$"
regexp="y"
enabled="y"
sequence="100"
script="map_shops"
>
</alias>
<alias
match="^mapper train\w*$"
regexp="y"
enabled="y"
sequence="100"
script="map_trainers"
>
</alias>
<alias
match="^mapper quest\w*$"
regexp="y"
enabled="y"
sequence="100"
script="map_quests"
>
</alias>
<alias
match="^mapper heal\w*$"
regexp="y"
enabled="y"
sequence="100"
script="map_healers"
>
</alias>
<alias
match="mapper goto *"
enabled="y"
sequence="100"
script="map_goto"
>
</alias>
<alias
match="mapper where *"
enabled="y"
sequence="100"
script="map_where"
>
</alias>
<alias
match="^mapper book\w*$"
regexp="y"
enabled="y"
sequence="100"
script="map_bookmarks"
>
</alias>
<alias
match="mapper resume"
enabled="y"
sequence="100"
script="map_resume"
>
</alias>
<!-- cancel speedwalking -->
<alias
match="mapper stop"
enabled="y"
sequence="100"
script="mapper.cancel_speedwalk"
>
</alias>
<!-- show/hide mapper -->
<alias
match="mapper hide"
enabled="y"
sequence="100"
script="mapper.hide"
>
</alias>
<alias
match="mapper show"
enabled="y"
sequence="100"
script="mapper.show"
>
</alias>
</aliases>
<triggers>
<!-- auto-swim -->
<trigger
enabled="y"
match="There's water ahead of you. You'll have to * to make it through."
sequence="100"
>
<send>%1</send>
</trigger>
<trigger
enabled="y"
match="You'll have to swim to make it through the water in that direction."
send_to="12"
sequence="100"
>
<send>
if last_direction_moved then
Send ("swim " .. last_direction_moved)
end -- if
</send>
</trigger>
<!-- auto-open -->
<trigger
enabled="y"
regexp="y"
match="^There is a door in the way"
send_to="12"
sequence="100"
>
<send>
if last_direction_moved then
Send ("open door " .. last_direction_moved)
end -- if
</send>
</trigger>
<!-- various messages that cancel speedwalks -->
<trigger
enabled="y"
match="Now now\, don\'t be so hasty\!$"
regexp="y"
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="^You cannot walk through"
regexp="y"
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="As you stroll in, you feel your feet slipping on something slimy."
script="mapper.cancel_speedwalk"
sequence="100"
>
<send>stand</send>
</trigger>
<trigger
enabled="y"
match="The door is locked."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You are regaining balance and are unable to move."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You are surrounded by a pocket of air and so must move normally through water."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You fumble about drunkenly."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You are asleep and can do nothing. WAKE will attempt to wake you."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You must be standing first."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You need to use a boat, fly, or swim underwater to go there."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="You can't * while sitting."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
regexp="y"
match="^You dream about "
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="There is no exit in that direction."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
<trigger
enabled="y"
match="Alas, you cannot go that way."
script="mapper.cancel_speedwalk"
sequence="100"
>
</trigger>
</triggers>
<!-- Plugin help -->
<aliases>
<alias
script="OnHelp"
match="mapper help"
enabled="y"
>
</alias>
</aliases>
<!-- Script -->
<script>
local show_vnums = &show_vnums;
local show_timing = &show_timing;
local show_completed = &show_completed;
local show_database_mods = &show_database_mods;
local show_other_areas = &show_other_areas;
local show_up_down = &show_up_down;
local show_area_exits = &show_area_exits;
local speedwalk_prefix = "&speedwalk_prefix;"
<![CDATA[
require "serialize"
require "checkplugin"
mapper = require "mapper"
default_config = {
-- assorted colours
BACKGROUND_COLOUR = { name = "Background", colour = ColourNameToRGB "lightseagreen", },
ROOM_COLOUR = { name = "Room", colour = ColourNameToRGB "cyan", },
EXIT_COLOUR = { name = "Exit", colour = ColourNameToRGB "darkgreen", },
EXIT_COLOUR_UP_DOWN = { name = "Exit up/down", colour = ColourNameToRGB "darkmagenta", },
EXIT_COLOUR_IN_OUT = { name = "Exit in/out", colour = ColourNameToRGB "#3775E8", },
OUR_ROOM_COLOUR = { name = "Our room", colour = ColourNameToRGB "black", },
UNKNOWN_ROOM_COLOUR = { name = "Unknown room", colour = ColourNameToRGB "#00CACA", },
DIFFERENT_AREA_COLOUR = { name = "Another area", colour = ColourNameToRGB "#009393", },
SHOP_FILL_COLOUR = { name = "Shop", colour = ColourNameToRGB "darkolivegreen", },
POSTOFFICE_FILL_COLOUR = { name = "Post Office", colour = ColourNameToRGB "yellowgreen", },
BANK_FILL_COLOUR = { name = "Bank", colour = ColourNameToRGB "gold", },
NEWSROOM_FILL_COLOUR = { name = "Newsroom", colour = ColourNameToRGB "lightblue", },
MAPPER_NOTE_COLOUR = { name = "Messages", colour = ColourNameToRGB "lightgreen" },
ROOM_NAME_TEXT = { name = "Room name text", colour = ColourNameToRGB "#BEF3F1", },
ROOM_NAME_FILL = { name = "Room name fill", colour = ColourNameToRGB "#105653", },
ROOM_NAME_BORDER = { name = "Room name box", colour = ColourNameToRGB "black", },
AREA_NAME_TEXT = { name = "Area name text", colour = ColourNameToRGB "#BEF3F1",},
AREA_NAME_FILL = { name = "Area name fill", colour = ColourNameToRGB "#105653", },
AREA_NAME_BORDER = { name = "Area name box", colour = ColourNameToRGB "black", },
FONT = { name = get_preferred_font {"Dina", "Lucida Console", "Fixedsys", "Courier", "Sylfaen",} ,
size = 8
} ,
-- size of map window
WINDOW = { width = 400, height = 400 },
-- how far from where we are standing to draw (rooms)
SCAN = { depth = 30 },
-- speedwalk delay
DELAY = { time = 0.3 },
-- how many seconds to show "recent visit" lines (default 3 minutes)
LAST_VISIT_TIME = { time = 60 * 3 },
}
local rooms = {}
local areas = {}
local environments = {}
local user_terrain_colour = {}
room_not_in_database = {}
room_in_database = {}
function dbcheck (code)
if code ~= sqlite3.OK and -- no error
code ~= sqlite3.ROW and -- completed OK with another row of data
code ~= sqlite3.DONE then -- completed OK, no more rows
local err = db:errmsg () -- the rollback will change the error message
db:exec ("ROLLBACK") -- rollback any transaction to unlock the database
error (err, 2) -- show error in caller's context
end -- if
end -- dbcheck
function fixsql (s)
if s then
return "'" .. (string.gsub (s, "'", "''")) .. "'" -- replace single quotes with two lots of single quotes
else
return "NULL"
end -- if
end -- fixsql
function fixbool (b)
if b then
return 1
else
return 0
end -- if
end -- fixbool
function save_room_to_database (uid, title)
assert (uid, "No UID supplied to save_room_to_database")
dbcheck (db:execute (string.format (
"INSERT INTO rooms (uid, name, area, date_added) VALUES (%s, %s, '0', DATETIME('NOW'));",
fixsql (uid),
fixsql (title)
)))
dbcheck (db:execute (string.format ([[
INSERT INTO rooms_lookup (uid, name) VALUES (%s, %s);
]], fixsql (uid),
fixsql (title)
)))
room_not_in_database [uid] = false
if show_database_mods then
mapper.mapprint ("Added room", uid, "to database. Name:", title)
end -- if
end -- function save_room_to_database
function save_exits_to_database (uid, exits)
local room = rooms [uid]
db:exec ("BEGIN TRANSACTION;")
for dir in string.gmatch (exits, "[^,]+") do
-- fix up in and out
dir = ({ ['i'] = "in", o = "out", }) [dir] or dir
dbcheck (db:execute (string.format ([[
INSERT INTO exits (dir, fromuid, touid, date_added)
VALUES (%s, %s, %s, DATETIME('NOW'));
]], fixsql (dir), -- direction (eg. "n")
fixsql (uid), -- from current room
fixsql (0) -- destination room (not known)
)))
if show_database_mods then
mapper.mapprint ("Added exit", dir, "from room", uid, "to database.")
end -- if
room.exits [dir] = "0"
end -- for each exit
db:exec ("COMMIT;")
end -- function save_room_to_database
function save_full_exits_to_database (uid, exits)
local room = rooms [uid]
db:exec ("BEGIN TRANSACTION;")
for exit in string.gmatch (exits, "[^,]+") do
dir, touid = string.match (exit, "^(%a+)%((%d+)%)$")
if dir then
-- fix up in and out
dir = ({ ['i'] = "in", o = "out", }) [dir] or dir
dbcheck (db:execute (string.format ([[
INSERT INTO exits (dir, fromuid, touid, date_added)
VALUES (%s, %s, %s, DATETIME('NOW'));
]], fixsql (dir), -- direction (eg. "n")
fixsql (uid), -- from current room
fixsql (touid) -- destination room
)))
if show_database_mods then
mapper.mapprint ("Added exit", dir, "from room", uid, "to room", touid, "to database.")
end -- if
room.exits [dir] = touid
else
mapper.maperror ("Cannot make sense of:", exit)
end -- if can decode
end -- for each exit
db:exec ("COMMIT;")
end -- function save_full_exits_to_database
function fix_up_exit ()
local room = rooms [from_room]
dbcheck (db:execute (string.format ([[
UPDATE exits SET touid = %s WHERE fromuid = %s AND dir = %s;
]],
fixsql (current_room), -- destination room
fixsql (from_room), -- from previous room
fixsql (last_direction_moved) -- direction (eg. "n")
)))
if show_database_mods then
mapper.mapprint ("Fixed exit", last_direction_moved, "from room", from_room, "to be to", current_room)
end -- if
room.exits [last_direction_moved] = current_room
last_direction_moved = nil
from_room = nil
end -- fix_up_exit
function save_environment_to_database (uid, s)
local room = rooms [uid]
dbcheck (db:execute (string.format ([[
UPDATE rooms SET terrain = %s WHERE uid = %s;
]],
fixsql (s), -- environment
fixsql (uid) -- room
)))
room.terrain = s
if show_database_mods then
mapper.mapprint ("Fixed room", uid, "to have environment:", s)
end -- if
end -- save_environment_to_database
function save_info_to_database (uid, s)
local room = rooms [uid]
dbcheck (db:execute (string.format ([[
UPDATE rooms SET info = %s WHERE uid = %s;
]],
fixsql (s), -- info
fixsql (uid) -- room
)))
room.info = s
if show_database_mods then
mapper.mapprint ("Fixed room", uid, "to have info:", s)
end -- if
end -- save_info_to_database
function save_coordinates_to_database (uid, s)
local room = rooms [uid]
local area, x, y, z = string.match (s, "^(.-),([%d-]+),([%d-]+),([%d-]+)")
if x then
dbcheck (db:execute (string.format ([[
UPDATE rooms SET x = %i, y = %i, z = %i, area = %s WHERE uid = %s;
]],
x, y, z, fixsql (area), -- coordinates, area
fixsql (uid) -- room
)))
room.x = x
room.y = y
room.z = z
room.area = area
if show_database_mods then
mapper.mapprint ("Fixed room", uid, "to have coordinates:", x, y, z, "and area", area)
end -- if
else
mapper.maperror ("Cannot make sense of coordinates:", s)
end -- if
end -- save_coordinates_to_database
function load_room_from_database (uid)
local room
assert (uid, "No UID supplied to load_room_from_database")
-- if not in database, don't look again
if room_not_in_database [uid] then
return nil
end -- no point looking
for row in db:nrows(string.format ("SELECT * FROM rooms WHERE uid = %s", fixsql (uid))) do
room = {
name = row.name,
area = row.area,
building = row.building,
terrain = row.terrain,
info = row.info,
notes = row.notes,
x = row.x,
y = row.y,
z = row.z,
exits = {} }
for exitrow in db:nrows(string.format ("SELECT * FROM exits WHERE fromuid = %s", fixsql (uid))) do
room.exits [exitrow.dir] = tostring (exitrow.touid)
end -- for each exit
end -- finding room
if room then
rooms [uid] = room
for row in db_bm:nrows(string.format ("SELECT * FROM bookmarks WHERE uid = %s", fixsql (uid))) do
rooms [uid].notes = row.notes
end -- finding room
return room
end -- if found
room_not_in_database [uid] = true
return nil
end -- load_room_from_database
function create_tables ()
-- create rooms table
dbcheck (db:execute[[
PRAGMA foreign_keys = ON;
PRAGMA journal_mode = WAL;
CREATE TABLE IF NOT EXISTS areas (
areaid INTEGER PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL, -- vnum or how the MUD identifies the area
name TEXT, -- name of area
date_added DATE, -- date added to database
UNIQUE (uid)
);
CREATE TABLE IF NOT EXISTS environments (
environmentid INTEGER PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL, -- code for the environment
name TEXT, -- name of environment
color INTEGER, -- ANSI colour code
date_added DATE, -- date added to database
UNIQUE (uid)
);
CREATE INDEX IF NOT EXISTS name_index ON environments (name);
CREATE TABLE IF NOT EXISTS rooms (
roomid INTEGER PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL, -- vnum or how the MUD identifies the room
name TEXT, -- name of room
area TEXT, -- which area
building TEXT, -- which building it is in
terrain TEXT, -- eg. road OR water
info TEXT, -- eg. shop,postoffice
notes TEXT, -- player notes
x INTEGER,
y INTEGER,
z INTEGER,
date_added DATE, -- date added to database
UNIQUE (uid)
);
CREATE INDEX IF NOT EXISTS info_index ON rooms (info);
CREATE INDEX IF NOT EXISTS terrain_index ON rooms (terrain);
CREATE INDEX IF NOT EXISTS area_index ON rooms (area);
CREATE TABLE IF NOT EXISTS exits (
exitid INTEGER PRIMARY KEY AUTOINCREMENT,
dir TEXT NOT NULL, -- direction, eg. "n", "s"
fromuid STRING NOT NULL, -- exit from which room (in rooms table)
touid STRING NOT NULL, -- exit to which room (in rooms table)
date_added DATE, -- date added to database
FOREIGN KEY(fromuid) REFERENCES rooms(uid)
);
CREATE INDEX IF NOT EXISTS fromuid_index ON exits (fromuid);
CREATE INDEX IF NOT EXISTS touid_index ON exits (touid);
]])
-- check if rooms_lookup table exists
local table_exists
for a in db:nrows "SELECT * FROM sqlite_master WHERE name = 'rooms_lookup' AND type = 'table'" do
table_exists = true
end -- for
if not table_exists then
dbcheck (db:execute "CREATE VIRTUAL TABLE rooms_lookup USING FTS3(uid, name);")
-- in case we only deleted the rooms_lookup table to save space in the download
dbcheck (db:execute "INSERT INTO rooms_lookup (uid, name) SELECT uid, name FROM rooms;")
end -- if
-- create bookmarks and terrain colours table in separate database
dbcheck (db_bm:execute[[
PRAGMA foreign_keys = ON;
CREATE TABLE IF NOT EXISTS bookmarks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL, -- vnum of room
notes TEXT, -- user notes
date_added DATE, -- date added to database
UNIQUE (uid)
);
CREATE TABLE IF NOT EXISTS terrain (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, -- terrain name
color INTEGER, -- RGB code
date_added DATE, -- date added to database
UNIQUE (name)
);
]])
end -- function create_tables
function get_room (uid)
-- check we got room at all
if not uid then
-- return nil
end -- if
-- look it up
local ourroom = rooms [uid]
-- not cached - see if in database
if not ourroom then
ourroom = load_room_from_database (uid)
rooms [uid] = ourroom -- cache for later
end -- not in cache
if not ourroom then
return nil
end -- if
local room = copytable.deep (ourroom)
room.area = areas [room.area] or string.format ("Area %s", room.area or "<unknown>")
if uid == current_room then
current_area = room.area
end -- if
-- build hover message
local environmentname = room.terrain
if tonumber (environmentname) then
environmentname = environments [tonumber (environmentname)]
end -- convert to name
local terrain = ""
if environmentname then
terrain = "\nTerrain: " .. capitalize (environmentname)
end -- if terrain known
local info = ""
if room.info then
info = "\nInfo: " .. capitalize (room.info)
end -- if info known
local notes = ""
if room.notes then
notes = "\nBookmark: " .. room.notes
end -- if notes
local texits = {}
for dir in pairs (room.exits) do
table.insert (texits, dir)
end -- for
table.sort (texits)
local areaname = room.area or "Unknown"
if tonumber (areaname) then
areaname = areas [tonumber (areaname)]
end -- convert to name
room.hovermessage = string.format (
"%s\tExits: %s\nRoom: %s\nArea: %s%s%s%s",
room.name,
table.concat (texits, ", "),
uid,
areaname,
terrain,
info,
notes
-- depth,
-- table.concat (path, ",")
)
room.bordercolour = config.ROOM_COLOUR.colour
room.borderpen = 0 -- solid
room.borderpenwidth = 1
room.fillcolour = 0xff0000
room.fillbrush = 1 -- no fill
-- special room fill colours
if room.info then
if string.match (room.info, "shop") then
room.fillcolour = config.SHOP_FILL_COLOUR.colour
room.fillbrush = 8
elseif string.match (room.info, "postoffice") then
room.fillcolour = config.POSTOFFICE_FILL_COLOUR.colour
room.fillbrush = 8
elseif string.match (room.info, "bank") then
room.fillcolour = config.BANK_FILL_COLOUR.colour
room.fillbrush = 8
elseif string.match (room.info, "newsroom") then
room.fillcolour = config.NEWSROOM_FILL_COLOUR.colour
room.fillbrush = 8
end -- if
else
-- use terrain colour
if environmentname then
if user_terrain_colour [environmentname] then
room.fillcolour = user_terrain_colour [environmentname]
room.fillbrush = 0 -- solid
elseif terrain_colours [environmentname] then
room.fillcolour = colour_lookup [terrain_colours [environmentname]]
room.fillbrush = 0 -- solid
end
end -- if environmentname
end -- if
if uid == current_room then
room.bordercolour = config.OUR_ROOM_COLOUR.colour
room.borderpenwidth = 2
elseif room.area ~= current_area then
room.bordercolour = config.DIFFERENT_AREA_COLOUR.colour
end -- not in this area
return room
end -- get_room
function room_edit_bookmark (room, uid)
local notes, found
for row in db_bm:nrows(string.format ("SELECT * FROM bookmarks WHERE uid = %s", fixsql (uid))) do
notes = row.notes
found = true
end -- finding room
if found then
newnotes = utils.inputbox ("Modify room comment (clear it to delete from database)", room.name, notes)
else
newnotes = utils.inputbox ("Enter room comment (creates a bookmark for this room)", room.name, notes)
end -- if
if not newnotes then
return
end -- if cancelled
if newnotes == "" then
if not found then
mapper.mapprint ("No comment entered, bookmark not saved.")
return
else
dbcheck (db_bm:execute (string.format (
"DELETE FROM bookmarks WHERE uid = %s;",
fixsql (uid)
)))
mapper.mapprint ("Bookmark for room", uid, "deleted. Was previously:", notes)
rooms [uid].notes = nil
return
end -- if
end -- if
if notes == newnotes then
return -- no change made
end -- if
if found then
dbcheck (db_bm:execute (string.format (
"UPDATE bookmarks SET notes = %s, date_added = DATETIME('NOW') WHERE uid = %s;",
fixsql (newnotes),
fixsql (uid)
)))
mapper.mapprint ("Bookmark for room", uid, "changed to:", newnotes)
else
dbcheck (db_bm:execute (string.format (
"INSERT INTO bookmarks (uid, notes, date_added) VALUES (%s, %s, DATETIME('NOW'));",
fixsql (uid),
fixsql (newnotes)
)))
mapper.mapprint ("Bookmark added to room", uid, ":", newnotes)
end -- if
rooms [uid].notes = newnotes
end -- room_edit_bookmark
function room_edit_terrain_colour (room, uid)
if not room.terrain then
utils.msgbox ("This room does not have a terrain type", "Unknown terrain!", "ok", "!", 1)
return
end -- not known
local environmentname = room.terrain
if tonumber (environmentname) then
environmentname = environments [tonumber (environmentname)]
end -- convert to name
local colour
local colourtype = terrain_colours [environmentname]
if colourtype then
colour = colour_lookup [colourtype]
end -- if type known
if user_terrain_colour [environmentname] then
colour = user_terrain_colour [environmentname]
end -- if already have user colour
local newcolour = PickColour (colour or 0x000000)
if newcolour == -1 or newcolour == colour then
return
end -- cancelled
if user_terrain_colour [environmentname] then
dbcheck (db_bm:execute (string.format (
"UPDATE terrain SET color = %s, date_added = DATETIME('NOW') WHERE name = %s;",
fixsql (newcolour),
fixsql (environmentname)
)))
mapper.mapprint ("Colour for terrain '" .. environmentname .. "' changed to:", RGBColourToName (newcolour))
else
dbcheck (db_bm:execute (string.format (
"INSERT INTO terrain (name, color, date_added) VALUES (%s, %s, DATETIME('NOW'));",
fixsql (environmentname),
fixsql (newcolour)
)))
mapper.mapprint ("Colour for terrain '" .. environmentname .. "' is now", RGBColourToName (newcolour))
end -- if
user_terrain_colour [environmentname] = newcolour
mapper.draw (current_room)
end -- room_edit_terrain_colour
function room_add_exit (room, uid)
local available = {
n = "North",
s = "South",
e = "East",
w = "West",
u = "Up",
d = "Down",
ne = "Northeast",
sw = "Southwest",
nw = "Northwest",
se = "Southeast",
['in'] = "In",
out = "Out",
} -- end of available
-- remove existing exits
for k in pairs (room.exits) do
available [k] = nil
end -- for
if next (available) == nil then
utils.msgbox ("All exits already used.", "No free exits!", "ok", "!", 1)
return
end -- not known
local chosen_exit = utils.listbox ("Choose exit to add", "Exits ...", available )
if not chosen_exit then
return
end
exit_destination = utils.inputbox ("Enter destination room identifier (number) for " .. available [chosen_exit], room.name, "")
if not exit_destination then
return
end -- cancelled
-- look it up
local dest_room = rooms [exit_destination]
-- not cached - see if in database
if not dest_room then
dest_room = load_room_from_database (exit_destination)
rooms [exit_destination] = dest_room -- cache for later
end -- not in cache
if not dest_room then
utils.msgbox ("Room " .. exit_destination .. " does not exist.", "Room does not exist!", "ok", "!", 1)
return
end -- if still not there
dbcheck (db:execute (string.format ([[
INSERT INTO exits (dir, fromuid, touid, date_added)
VALUES (%s, %s, %s, DATETIME('NOW'));
]], fixsql (chosen_exit), -- direction (eg. "n")
fixsql (uid), -- from current room
fixsql (exit_destination) -- destination room
)))
if show_database_mods then
mapper.mapprint ("Added exit", available [chosen_exit], "from room", uid, "to room", exit_destination, "to database.")
end -- if
-- update in-memory table
rooms [uid].exits [chosen_exit] = exit_destination
mapper.draw (current_room)
end -- room_add_exit
function room_delete_exit (room, uid)
local available = {
n = "North",
s = "South",
e = "East",
w = "West",
u = "Up",
d = "Down",
ne = "Northeast",
sw = "Southwest",
nw = "Northwest",
se = "Southeast",
['in'] = "In",
out = "Out",
} -- end of available
-- remove non-existent exits
for k in pairs (available) do
if room.exits [k] then
available [k] = available [k] .. " --> " .. room.exits [k]
else
available [k] = nil
end -- if not a room exit
end -- for
if next (available) == nil then
utils.msgbox ("There are no exits from this room.", "No exits!", "ok", "!", 1)
return
end -- not known
local chosen_exit = utils.listbox ("Choose exit to delete", "Exits ...", available )
if not chosen_exit then
return
end
dbcheck (db:execute (string.format ([[
DELETE FROM exits WHERE dir = %s AND fromuid = %s;
]], fixsql (chosen_exit), -- direction (eg. "n")
fixsql (uid) -- from current room
)))
if show_database_mods then
mapper.mapprint ("Deleted exit", available [chosen_exit], "from room", uid, "from database.")
end -- if
-- update in-memory table
rooms [uid].exits [chosen_exit] = nil
mapper.draw (current_room)
end -- room_delete_exit
function room_change_exit (room, uid)
local available = {
n = "North",
s = "South",
e = "East",
w = "West",
u = "Up",
d = "Down",
ne = "Northeast",
sw = "Southwest",
nw = "Northwest",
se = "Southeast",
['in'] = "In",
out = "Out",
} -- end of available
-- remove non-existent exits
for k in pairs (available) do
if room.exits [k] then
available [k] = available [k] .. " --> " .. room.exits [k]
else
available [k] = nil
end -- if not a room exit
end -- for
if next (available) == nil then
utils.msgbox ("There are no exits from this room.", "No exits!", "ok", "!", 1)
return
end -- not known
local chosen_exit = utils.listbox ("Choose exit to change destination of:", "Exits ...", available )
if not chosen_exit then
return
end
exit_destination = utils.inputbox ("Enter destination room identifier (number) for " .. available [chosen_exit], room.name, "")
if not exit_destination then
return
end -- cancelled
-- look it up
local dest_room = rooms [exit_destination]
-- not cached - see if in database
if not dest_room then
dest_room = load_room_from_database (exit_destination)
rooms [exit_destination] = dest_room -- cache for later
end -- not in cache
if not dest_room then
utils.msgbox ("Room " .. exit_destination .. " does not exist.", "Room does not exist!", "ok", "!", 1)
return
end -- if still not there
dbcheck (db:execute (string.format ([[
UPDATE exits SET touid = %s WHERE dir = %s AND fromuid = %s;
]], fixsql (exit_destination),
fixsql (chosen_exit), -- direction (eg. "n")
fixsql (uid) -- from current room
)))
if show_database_mods then
mapper.mapprint ("Modified exit", available [chosen_exit], "from room", uid, "to be to room", exit_destination, "in database.")
end -- if
-- update in-memory table
rooms [uid].exits [chosen_exit] = exit_destination
mapper.draw (current_room)
end -- room_change_exit
function change_room_area (room, uid)
if next (areas) == nil then
mapper.maperror("There are no available areas to choose from.")
return
end -- if
local chosen_area = utils.listbox ("Choose the area this room belongs to:", "Areas ...", areas)
if not chosen_area then
return
end -- if
rooms[uid].area = chosen_area
mapper.draw (current_room)
dbcheck (db:execute (string.format ([[
UPDATE rooms SET area = %s WHERE uid = %s;
]], fixsql (chosen_area), -- area (e.g. "1" for "western ithmia")
fixsql (uid) -- from current room
)))
end -- change_room_area
function add_area (room, uid)
local roomname
local roomarea
for row in db:nrows(string.format ("SELECT name, area FROM rooms WHERE uid = %s", fixsql (uid))) do
roomname = row.name
roomarea = row.area
end -- finding room
if roomname == nil then
mapper.maperror("Cannot find this room in the database")
return
end -- if
local area_name = utils.inputbox ("Name for area: " .. roomarea,
"Choose the name for this area",
areas [roomarea] )
if not area_name or area_name == "" then
return
end -- if
db:exec ("BEGIN TRANSACTION")
-- get rid of old area description, if any
local exists = db:execute (string.format (
"DELETE FROM areas WHERE uid = %s;",
fixsql (roomarea)
)) == sqlite3.OK
dbcheck (db:execute (string.format (
"INSERT INTO areas (uid, name, date_added) VALUES (%s, %s, DATETIME('NOW'));",
fixsql (roomarea),
fixsql (area_name)
)))
db:exec ("COMMIT")
local action = "Added"
if exists then
action = "Changed"
end -- if
mapper.mapprint (string.format ("%s area '%s' with area code '%s'",
action, area_name, roomarea))
areas [roomarea] = area_name
mapper.draw (current_room)
end -- add_area
function room_click (uid, flags)
-- check we got room at all
if not uid then
return nil
end -- if
-- look it up
local room = rooms [uid]
-- not cached - see if in database
if not room then
room = load_room_from_database (uid)
rooms [uid] = room -- cache for later
end -- not in cache
if not room then
return
end -- if still not there
local handlers = {
{ name = "Edit bookmark", func = room_edit_bookmark} ,
{ name = "Edit terrain colour", func = room_edit_terrain_colour} ,
{ name = "-", } ,
-- { name = "^Exits", } ,
{ name = "Add Exit", func = room_add_exit} ,
{ name = "Change Exit", func = room_change_exit} ,
{ name = "Delete Exit", func = room_delete_exit} ,
{ name = "-", } ,
{ name = "Set area for room", func = change_room_area} ,
{ name = "Update area name", func = add_area} ,
} -- handlers
local t, tf = {}, {}
for _, v in pairs (handlers) do
table.insert (t, v.name)
tf [v.name] = v.func
end -- for
local choice = WindowMenu (mapper.win,
WindowInfo (mapper.win, 14),
WindowInfo (mapper.win, 15),
table.concat (t, "|"))
local f = tf [choice]
if f then
f (room, uid)
end -- if handler found
end -- room_click
function OnPluginInstall ()
config = {} -- in case not found
-- get saved configuration
assert (loadstring (GetVariable ("config") or "")) ()
-- allow for additions to config
for k, v in pairs (default_config) do
config [k] = config [k] or v
end -- for
-- initialize mapper engine
mapper.init { config = config, -- colours, timing etc.
get_room = get_room, -- get_room (uid) called to get room info
show_help = OnHelp, -- to show help
room_click = room_click, -- called on RH click on room square
timing = show_timing, -- want to see timing
show_completed = show_completed, -- want to see "Speedwalk completed." message
show_other_areas = show_other_areas, -- want to see areas other than the current one?
show_up_down = show_up_down, -- want to follow up/down exits?
show_area_exits = show_area_exits, -- want to see area exits?
speedwalk_prefix = speedwalk_prefix, -- how to speedwalk
}
mapper.mapprint (string.format ("MUSHclient mapper installed, version %0.1f", mapper.VERSION))
-- open databases on disk
db = assert (sqlite3.open(GetInfo (66) .. Trim (WorldAddress ()) .. "_" .. WorldPort () .. ".db"))
db_bm = assert (sqlite3.open(GetInfo (66) .. Trim (WorldAddress ()) .. "_" .. WorldPort () .. "_bookmarks.db"))
create_tables () -- create database structure if necessary
-- grab all area names
for row in db:nrows("SELECT * FROM areas") do
areas [row.uid] = row.name
end -- finding areas
-- grab all user terrain info
for row in db_bm:nrows("SELECT * FROM terrain") do
user_terrain_colour [row.name] = row.color
end -- finding terrains
-- grab all environment names
for row in db:nrows("SELECT * FROM environments") do
environments [tonumber (row.uid)] = row.name
terrain_colours [row.name] = tonumber (row.color)
end -- finding environments
end -- OnPluginInstall
function OnPluginEnable ()
mapper.show ()
end -- OnPluginDisable
function OnPluginDisable ()
mapper.hide ()
end -- OnPluginDisable
-- hide window on removal
function OnPluginClose ()
mapper.hide ()
-- close databases
db:close()
db_bm:close()
end -- OnPluginClose
function OnPluginSaveState ()
mapper.save_state ()
SetVariable ("config", "config = " .. serialize.save_simple (config))
end -- OnPluginSaveState
terrain_colours = {}
-- ANSI colours lookup (for terrain_colours)
colour_lookup = {
[0] = ColourNameToRGB "black",
[1] = ColourNameToRGB "maroon",
[2] = ColourNameToRGB "green",
[3] = ColourNameToRGB "olive",
[4] = ColourNameToRGB "navy",
[5] = ColourNameToRGB "purple",
[6] = ColourNameToRGB "teal",
[7] = ColourNameToRGB "silver",
[8] = ColourNameToRGB "gray",
[9] = ColourNameToRGB "red",
[10] = ColourNameToRGB "lime",
[11] = ColourNameToRGB "yellow",
[12] = ColourNameToRGB "blue",
[13] = ColourNameToRGB "magenta",
[14] = ColourNameToRGB "cyan",
[15] = ColourNameToRGB "white",
} -- end of colour_lookup
-- here when location changes, eg. : Room.Num 7476
function got_room_number (s)
local room_number = s
if not room_number then
return
end -- no room number
current_room = room_number
mapper.draw (room_number)
if expected_exit == "0" and from_room then
fix_up_exit ()
end -- exit was wrong
end -- got_room_number
-- we got a room name, eg. : Room.Brief On the edge of a great plain
function got_room_name (s)
local brief = s
if not current_room then
return
end -- don't have room
local room = rooms [current_room]
-- not cached - see if in database
if not room then
room = load_room_from_database (current_room)
end -- not in cache
if not room then
save_room_to_database (current_room, brief)
mapper.draw (current_room) -- redraw room with name
end -- if room not there
end -- got_room_name
-- we got room exits, eg. : Room.Exits ne,sw,nw
function got_room_exit (s)
-- don't do if we are expecting full exits at some stage
if full_exits_found then
return
end -- if
local exits = string.match (s, "^([%a,]+)$")
if not (current_room and exits) then
return
end -- if
local room = rooms [current_room]
-- not cached - see if in database
if not room then
room = load_room_from_database (current_room)
end -- not in cache
if room and next (room.exits) == nil then
save_exits_to_database (current_room, exits)
mapper.draw (current_room) -- redraw room with exits
end -- need to save exits
end -- got_room_exit
function got_vitals (s)
-- ignore
end -- function got_vitals
-- we got room exits, eg. : Room.FullExits ne(8564),w(8428)
function got_room_full_exits (s)
full_exits_found = true
local exits = string.match (s, "^([%a,(%d)]+)$")
if not (current_room and exits) then
return
end -- if
local room = rooms [current_room]
-- not cached - see if in database
if not room then
room = load_room_from_database (current_room)
end -- not in cache
if room and next (room.exits) == nil then
save_full_exits_to_database (current_room, exits)
mapper.draw (current_room) -- redraw room with exits
end -- need to save exits
end -- got_room_exit
-- we got room environment, eg. : Urban
function got_environment (s)
if not current_room then
return
end -- if
local room = rooms [current_room]
-- not cached - see if in database
if not room then
room = load_room_from_database (current_room)
end -- not in cache
if room and room.terrain == nil then
save_environment_to_database (current_room, s)
mapper.draw (current_room) -- redraw room with environment
end -- need to save environment
end -- got_environment
-- we got room coordinates, eg. : "38,3,1,0"
function got_coordinates (s)
if not current_room then
return
end -- if
local room = rooms [current_room]
-- not cached - see if in database
if not room then
room = load_room_from_database (current_room)
end -- not in cache
if room and (room.area == nil or tonumber (room.area) == 0) then
save_coordinates_to_database (current_room, s)
mapper.draw (current_room) -- redraw room with area
end -- need to save environment
end -- got_coordinates
-- we got room info, eg. : shops,postoffice
function got_info (s)
if not current_room then
return
end -- if
local room = rooms [current_room]
-- not cached - see if in database
if not room then
room = load_room_from_database (current_room)
end -- not in cache
if room and room.info == nil then
save_info_to_database (current_room, s)
mapper.draw (current_room) -- redraw room with info
end -- need to save environment
end -- got_info
handlers = {
[1] = got_vitals, -- eg. "H:496/496 M:412/412 E:1380/1380 W:960/960 NL:89/100"
-- health mana endurance willpower experience
[2] = got_room_name, -- eg. "Continuing on the Parade of Zarathustra"
[3] = got_room_exit, -- eg. "n,s"
[4] = got_room_number, -- eg. "401"
[5] = got_room_full_exits, -- eg. "ne(8564),w(8428)"
[6] = got_environment, -- eg. "Urban"
[7] = got_coordinates, -- eg. "38,3,1,0"
[8] = got_info, -- eg. "shops,postoffice"
}
function OnPluginBroadcast (msg, id, name, text)
if id == "85f72d0e263d75df7bde6f00" then
local f = handlers [msg]
if f then
f (text)
end -- have handler
end -- if ATCP message
end
function map_find (name, line, wildcards)
local rooms = {}
local count = 0
-- find matching rooms using FTS3
for row in db:nrows(string.format ("SELECT uid, name FROM rooms_lookup WHERE rooms_lookup MATCH %s", fixsql (wildcards [1]))) do
rooms [row.uid] = true
count = count + 1
end -- finding room
-- see if nearby
mapper.find (
function (uid)
local room = rooms [uid]
if room then
rooms [uid] = nil
end -- if
return room, next (rooms) == nil
end, -- function
show_vnums, -- show vnum?
count, -- how many to expect
false -- don't auto-walk
)
end -- map_find
function map_find_special (which_ones)
local wanted_items = {}
for _, v in ipairs (which_ones) do
wanted_items [v:lower ()] = true
end
local rooms = {}
local count = 0
-- build table of special places (with info in them)
for row in db:nrows(string.format ("SELECT uid, name, info FROM rooms WHERE info IS NOT NULL")) do
if row.info ~= "" then
local wanted = false
local t = {}
for item in string.gmatch (row.info, "[^,]+") do
if wanted_items [item:lower ()] then
wanted = true
table.insert (t, capitalize (item))
end -- if
end -- for
if wanted then
rooms [row.uid] = table.concat(t, ", ")
count = count + 1
end -- if
end -- if
end -- finding room
-- find such places
mapper.find (
function (uid)
local room = rooms [uid]
if room then
rooms [uid] = nil
end -- if
return room, next (rooms) == nil -- room will be type of info (eg. shop)
end, -- function
show_vnums, -- show vnum?
count, -- how many to expect
false -- don't auto-walk
)
end -- map_find_special
--[[
for _, v in ipairs ({
-- "guild", "healer", "trainer", "questor",
}) do wanted_items [v] = true end
--]]
function map_shops (name, line, wildcards)
map_find_special { "shop", "postoffice", "bank", "newsroom", }
end -- map_shops
function map_trainers (name, line, wildcards)
map_find_special { "trainer", }
end -- map_trainers
function map_quests (name, line, wildcards)
map_find_special { "questor", }
end -- map_quests
function map_healers (name, line, wildcards)
map_find_special { "healers", }
end -- map_healers
function map_goto (name, line, wildcards)
local wanted = wildcards [1]
if current_room and wanted == current_room then
mapper.mapprint ("You are already in that room.")
return
end -- if
-- find desired room
mapper.find (
function (uid)
return uid == wanted, uid == wanted
end, -- function
show_vnums, -- show vnum?
1, -- how many to expect
true -- just walk there
)
end -- map_goto
function map_where (name, line, wildcards)
if not mapper.check_we_can_find () then
return
end -- if
local wanted = wildcards [1]
if current_room and wanted == current_room then
mapper.mapprint ("You are already in that room.")
return
end -- if
local paths = mapper.find_paths (current_room,
function (uid)
return uid == wanted, -- wanted room?
uid == wanted -- stop searching?
end)
local uid, item = next (paths, nil) -- extract first (only) path
-- nothing? room not found
if not item then
mapper.mapprint (string.format ("Room %s not found", wanted))
return
end -- if
-- turn into speedwalk
local path = mapper.build_speedwalk (item.path)
-- display it
mapper.mapprint (string.format ("Path to %s is: %s", wanted, path))
end -- map_where
function map_resume (name, line, wildcards)
local wanted = mapper.last_hyperlink_uid or mapper.last_speedwalk_uid
if not wanted then
mapper.print "No outstanding speedwalks or hyperlinks."
return
end -- if nothing to do
-- find desired room
mapper.find (
function (uid)
return uid == wanted, uid == wanted
end, -- function
show_vnums, -- show vnum?
1, -- how many to expect
true -- just walk there
)
end -- map_resume
function map_bookmarks (name, line, wildcards)
local rooms = {}
local count = 0
-- build table of special places (with info in them)
for row in db_bm:nrows(string.format ("SELECT uid, notes FROM bookmarks")) do
rooms [row.uid] = capitalize (row.notes)
count = count + 1
end -- finding room
-- find such places
mapper.find (
function (uid)
local room = rooms [uid]
if room then
rooms [uid] = nil
end -- if
return room, next (rooms) == nil -- room will be type of info (eg. shop)
end, -- function
show_vnums, -- show vnum?
count, -- how many to expect
false -- don't auto-walk
)
end -- map_bookmarks
function map_areas (name, line, wildcards)
local wanted_areas = {}
local count = 0
if next (areas) == nil then
mapper.maperror "No areas known."
return
end -- if
-- build table of all areas, keyed by area code
for k, v in pairs (areas) do
wanted_areas [k] = v
count = count + 1
end -- for
-- find all areas
mapper.find (
function (uid)
local room = rooms [uid]
local reason
-- if this room is in the list of wanted areas then save its path
if wanted_areas[room.area] then
reason = wanted_areas [room.area]
wanted_areas [room.area] = nil
end -- found one!
return reason, next (wanted_areas) == nil
end, -- function
show_vnums, -- show vnum?
count, -- how many to expect
false -- don't auto-walk
)
end -- map_areas
valid_direction = {
n = "n",
s = "s",
e = "e",
w = "w",
u = "u",
d = "d",
ne = "ne",
sw = "sw",
nw = "nw",
se = "se",
north = "n",
south = "s",
east = "e",
west = "w",
up = "u",
down = "d",
northeast = "ne",
northwest = "nw",
southeast = "se",
southwest = "sw",
['in'] = "in",
out = "out",
} -- end of valid_direction
-- try to detect when we send a movement command
function OnPluginSent (sText)
if valid_direction [sText] then
last_direction_moved = valid_direction [sText]
-- print ("Just moved", last_direction_moved)
if current_room and rooms [current_room] then
expected_exit = rooms [current_room].exits [last_direction_moved]
if expected_exit then
from_room = current_room
end -- if
-- print ("expected exit for this direction is to room", expected_exit)
end -- if
end -- if
end -- function
function OnPluginConnect ()
mapper.cancel_speedwalk ()
-- DoAfter (3, "look") -- force mapper update
end -- OnPluginConnect
function OnPluginDisconnect ()
mapper.cancel_speedwalk ()
end -- OnPluginConnect
function OnHelp ()
mapper.mapprint (string.format ("[MUSHclient mapper, version %0.1f]", mapper.VERSION))
mapper.mapprint (world.GetPluginInfo (world.GetPluginID (), 3))
end
function OnPluginListChanged ()
do_plugin_check_now ("85f72d0e263d75df7bde6f00", "ATCP_NJG") -- check we have ATCP plugin
end -- OnPluginListChanged
]]>
</script>
</muclient>
Jump to Line
Something went wrong with that request. Please try again.