Mapper Script for New Worlds Ateraan?
Re: Mapper Script for New Worlds Ateraan?
I happen to have built a semi-automatic mapper script for a MUD I play (Dark and Shattered Lands), which only uses room names, exits, and something to capture the prompt and relevant commands to do the heavy lifting for the mapping, and only needs intervention to shift rooms around into position (it uses a few aliases to manage that and various other situations where layout doesn't play nicely). It currently relies on a larger framework I have in place for the MUD, but it shouldn't be excessively difficult to modify to work without it.
Re: Mapper Script for New Worlds Ateraan?
Oh, awesome! I would really appreciate that. Provided you could also maybe give me a help file. Hah. Or Skype me and give me the run down real quick. Thanks. Skype - RyderOfTheNite. I'm usually on after 7 PM EST
Re: Mapper Script for New Worlds Ateraan?
I'll work on it. May be a few weeks before I have a version that is ready for prime time outside of its current framework (I don't have tons of time to code and debug). Once I have sometime, I'll post it here.
Re: Mapper Script for New Worlds Ateraan?
So, I have what I think should be a working, generic mapping script, as I mentioned previously. To use it, you will need to have the Simple Window Manager script installed (from here: http://forums.mudlet.org/viewtopic.php?f=6&t=3529), in addition to making certain triggers to capture specific events, as specified in the help section of the map script.
If you need help getting the necessary triggers setup, or of some issues crop up, please let me know, and I'll see what I can do to help.
-- Jor'Mox's Generic Map Script
-- 8/31/2016
-- v1.0
--
map = map or {}
map.help = [[
Jor'Mox's Generic Map Script
This script allows for semi-automatic mapping using just room names and exits. It is
a good idea to know the general layout of the area you are trying to map before
turning on mapping with this script, so as to minimize how much you need to move
things around to make it look how you want it to. The script will automatically
stretch out a map to make space for a room if it would overlap with another one, but
it is important to make sure that things line up properly, or you will have inaccurate
maps with duplicate sections in them.
It is up to YOU to create triggers that appropriately raise the following events, and
gather the necessary information. The way in which such things are displayed varies
dramatically from game to game, so any set of triggers for one game will likely not
work for the next.
Important Events for Proper Mapping
onMoveFail - raise this event to indicate that you attempted to move, but no move
was made
onVisionFail - raise this event to indicate that you moved successfully, but are
unable to gather some or all of the necessary info about the room
onRandomMove - raise this event to indicate that you moved, but do not know what
direction you moved in
onNewRoom - raise this event to indicate that a room has been detected, typically
after moving or looking to see the room you are currently in
onPrompt - raise this event to indicate a prompt has been detected, room name and
exits must be stored in map.prompt.room and map.prompt.exits before raising
this event
Important Commands (Aliases) for Proper Mapping
Fundamental Aliases
start mapping <optional area name> - use this command to start adding new content
to the map
stop mapping - use this command to stop mapping
save map - saves the map to a file (map.dat, located in the profile folder)
load map <optional 'local'> - loads the map from the location specified in the
download_path, or from the local copy
export area <area name> - exports a file to the profile folder with data for the
named area
import area <area name> - imports area data from a file created with export area,
must be located in profile folder
Mapping Aliases
map mode <simple, normal, or complex> - sets the mapping mode, determining what
exits are set automatically as you move around
set area <area name> - move the current room into the named area, area will be
created if it does not currently exist
shift <direction> - use this command to move the room you are currently in around
on the map
merge rooms - use this command to comine the room you are in with any other rooms
in the same location and with the same name
clear moves - use this command to clear the move queue after you attempt a move
that doesn't succeed, but for which there is no trigger indicating this with
the onMoveFail event
add door <direction> <optional none, open, closed, locked> <optional yes, no> -
adds a door in the given direction, defaulting to closed (use none to remove
a door), and defaulting 'no' for one-way status
add portal <entry command> - adds a portal that uses the given command for entry
set exit <direction> <roomID> - sets the given direction to connect, one way,
to the room with the specified roomID, used for very complex areas
Normal User Aliases
find me - use this command to search the entire map to try to locate you based on
room name and exits, typically not necessary, as this will be done anyway if
a person moves and their location is unknown
find path <room name> OR <room name> ; <area name> - used to find a walking path
to a room with the given name, in the given area if specified
set character <name> - sets the current character name (stored as map.character)
set recall - sets the current room as the recall room for the current character
]]
map.recall = map.recall or {}
map.character = map.character or ""
map.prompt = map.prompt or {}
map.configs = {
mode = "normal", -- can be simple, normal, or complex
x = 16,
y = 0,
w = "30%",
h = "40%",
origin = "topright",
download_path = "",
}
local function make_aliases()
map.aliases = map.aliases or {}
local id
local tbl = {
["Start Mapping Alias"] = {[[^start mapping(?: (.*))?$]], [[map.start_mapping(matches[2])]]},
["Stop Mapping Alias"] = {[[^stop mapping$]], [[map.stop_mapping()]]},
["Save Map Alias"] = {[[^save map$]], [[saveMap(getMudletHomeDir() .. "/map.dat")]]},
["Load Map Alias"] = {[[^load map(?: (local))?$]], [[map.load_map(matches[2])]]},
["Export Map Area Alias"] = {[[^export area (.*)]],[[map.export_area(matches[2])]]},
["Import Map Area Alias"] = {[[^import area (.*)]],[[map.import_area(matches[2])]]},
["Set Room Area Alias"] = {[[^set area (.*)$]], [[map.set_area(matches[2])]]},
["Set Map Mode Alias"] = {[[^map mode (\w+)$]],[[map.set_mode(matches[2])]]},
["Shift Room Alias"] = {[[^shift (.*)$]], [[map.shift_room(matches[2])]]},
["Merge Rooms Alias"] = {[[^merge rooms$]], [[map.merge_rooms()]]},
["Add Door Alias"] = {[[^add door (\w+)(?: (none|open|closed|locked)(?: (yes|no))?)?$]],[[map.set_door(matches[2],matches[3],matches[4])]]},
["Add Portal Alias"] = {[[^add portal (.*)$]],[[map.set_portal(matches[2])]]},
["Set Room Exit Alias"] = {[[^set exit (\w+) (\d+)]],[[map.set_exit(matches[2],matches[3])]]},
["Clear Moves Alias"] = {[[^clear moves$]], [[map.clear_moves()]]},
["Find Me Alias"] = {[[^find me$]], [[map.find_me()]]},
["Find Path Alias"] = {[[find path ([^;]+)(?:\s*;\s*(.+))?]],[[map.find_path(matches[2],matches[3])]]},
["Set Recall Alias"] = {[[^set recall$]],[[map.set_recall()]]},
["Set Character Alias"] = {[[^set character (.*)$]],[[map.character = matches[2]]},
}
for k,v in pairs(tbl) do
if map.aliases[k] and exists(map.aliases[k],"alias") ~= 0 then
killAlias(map.aliases[k])
end
id = tempAlias(v[1],v[2])
map.aliases[k] = id
end
end
local function config()
local configs = map.configs
map_mode = configs.mode
--print(configs.x,configs.y,configs.w,configs.h,configs.origin)
windowManager.add("mini_map","mapper",configs.x,configs.y,configs.w,configs.h,configs.origin)
windowManager.show("mini_map")
make_aliases()
end
local move_queue = {}
local prevRoom, prevName, prevExits
local currentRoom, currentName, currentExits, currentArea
local mapping, map_mode, downloading
local find_portal, vision_fail, room_detected, random_move
local exitmap = {
n = 'north', ne = 'northeast', nw = 'northwest', e = 'east',
w = 'west', s = 'south', se = 'southeast', sw = 'southwest',
u = 'up', d = 'down', ["in"] = 'in', out = 'out',
}
local short = {}
for k,v in pairs(exitmap) do
short[v] = k
end
local stubmap = {
north = 1, northeast = 2, northwest = 3, east = 4,
west = 5, south = 6, southeast = 7, southwest = 8,
up = 9, down = 10, ["in"] = 11, out = 12,
[1] = "north", [2] = "northeast", [3] = "northwest", [4] = "east",
[5] = "west", [6] = "south", [7] = "southeast", [8] = "southwest",
[9] = "up", [10] = "down", [11] = "in", [12] = "out",
}
local coordmap = {
[1] = {0,1,0}, [2] = {1,1,0}, [3] = {-1,1,0}, [4] = {1,0,0},
[5] = {-1,0,0}, [6] = {0,-1,0}, [7] = {1,-1,0}, [8] = {-1,-1,0},
[9] = {0,0,1}, [10] = {0,0,-1}, [11] = {0,0,0}, [12] = {0,0,0},
}
local reverse_dirs = {
north = "south", south = "north", west = "east", east = "west", up = "down",
down = "up", northwest = "southeast", northeast = "southwest", southwest = "northeast",
southeast = "northwest", ["in"] = "out", out = "in",
}
function doSpeedWalk()
-- we can do a lot here, this fires when a room is double clicked on, and is intended to speedwalk to it
print("Path to " .. getRoomName(speedWalkPath[#speedWalkPath]) .. ": " .. table.concat(speedWalkDir, ", "))
end
local function set_room(roomID)
-- moves the map to the new room
if currentRoom ~= roomID then
prevRoom = currentRoom
currentRoom = roomID
end
if getRoomName(currentRoom) ~= currentName then
prevName = currentName
prevExits = currentExits
currentName = getRoomName(currentRoom)
currentExits = getRoomExits(currentRoom)
end
currentArea = getRoomArea(currentRoom)
centerview(currentRoom)
end
local function add_door(roomID, dir, status)
-- create or remove a door in the designated direction
-- consider options for adding pickable and passable information
dir = exitmap[dir] or dir
if not table.contains(exitmap,dir) then error("Add Door: invalid direction.",2) end
status = assert(table.index_of({"none","open","closed","locked"},status),"Add Door: Invald status, must be none, open, closed, or locked") - 1
local exits = getRoomExits(roomID)
if not exits[dir] then
setExitStub(roomID,stubmap[dir],true)
end
if table.contains({"up","down"},dir) then
setRoomUserData(roomID,"door " .. dir, tostring(status))
else
setDoor(roomID,short[dir],status)
end
end
local function check_doors(roomID,exits)
-- looks to see if there are doors in designated directions
-- used for room comparison, can also be used for pathing purposes
local statuses = {"open","closed","locked",[0] = "none"}
local doors = getDoors(roomID)
local door_up = tonumber(getRoomUserData(roomID,"door up"))
door_up = door_up ~= 0 and door_up or nil
local door_down = tonumber(getRoomUserData(roomID,"door down"))
door_down = door_down ~= 0 and door_down or nil
doors["u"] = door_up
doors["d"] = door_down
local dir
for k,v in pairs(exits) do
dir = short[k] or short[v]
if not table.contains(doors,dir) then
return false
end
end
return true
end
local function find_room(name, area)
-- looks for rooms with a particular name, and if given, in a specific area
local rooms = searchRoom(name)
if type(area) == "string" then
local areas = getAreaTable() or {}
for k,v in pairs(areas) do
if string.lower(k) == string.lower(area) then
area = v
break
end
end
area = areas[area] or nil
end
for k,v in pairs(rooms) do
if string.lower(v) ~= string.lower(name) then
rooms[k] = nil
elseif area and getRoomArea(k) ~= area then
rooms[k] = nil
end
end
return rooms
end
local function getRoomStubs(roomID)
-- turns stub info into table similar to exit table
local stubs = getExitStubs(roomID)
if type(stubs) ~= "table" then stubs = {} end
local exits = {}
for k,v in pairs(stubs) do
exits[stubmap[v]] = 0
end
return exits
end
local function connect_rooms(ID1, ID2, dir1, dir2, no_check)
-- makes a connection between rooms
-- can make backwards connection without a check
local match = false
if not ID1 and ID2 and dir1 then error("Connect Rooms: Missing Required Arguments.",2) end
dir2 = dir2 or reverse_dirs[dir1]
setExit(ID1,ID2,stubmap[dir1])
if map_mode ~= "complex" then
local stubs = getRoomStubs(ID2)
if stubs[dir2] then match = true end
if (match or no_check) then setExit(ID2,ID1,stubmap[dir2]) end
end
end
local function check_room(roomID, name, exits)
-- check to see if room name and exits match expecations
if not roomID then error("Check Room Error: No ID",2) end
if name ~= getRoomName(roomID) then return false end
local t_exits = table.union(getRoomExits(roomID),getRoomStubs(roomID))
for k,v in ipairs(exits) do
if short[v] and not table.contains(t_exits,v) then return false end
t_exits[v] = nil
end
return table.is_empty(t_exits) or check_doors(roomID,t_exits)
end
local function stretch_map(dir,x,y,z)
-- stretches a map to make room for just added room that would overlap with existing room
local dx,dy,dz
for k,v in pairs(getAreaRooms(currentArea)) do
if v ~= currentRoom then
dx,dy,dz = getRoomCoordinates(v)
if dx >= x and string.find(dir,"east") then
dx = dx + 1
elseif dx <= x and string.find(dir,"west") then
dx = dx - 1
end
if dy >= y and string.find(dir,"north") then
dy = dy + 1
elseif dy <= y and string.find(dir,"south") then
dy = dy - 1
end
if dz >= z and string.find(dir,"up") then
dz = dz + 1
elseif dz <= z and string.find(dir,"down") then
dz = dz - 1
end
setRoomCoordinates(v,dx,dy,dz)
end
end
end
local function create_room(name, exits, dir, coords)
-- makes a new room with captured name and exits
-- links with other rooms as appropriate
-- links to adjacent rooms in direction of exits if in simple mode
if mapping then
print("New Room: " .. name .. "\n")
local newID = createRoomID()
addRoom(newID)
setRoomArea(newID, currentArea)
setRoomName(newID, name)
for k,v in ipairs(exits) do
if stubmap[v] then
setExitStub(newID, stubmap[v], true)
end
end
if dir then
connect_rooms(currentRoom, newID, dir)
elseif find_portal then
addSpecialExit(currentRoom, newID, find_portal)
setRoomUserData(newID,"portals",tostring(currentRoom)..":"..find_portal)
end
setRoomCoordinates(newID,unpack(coords))
if table.size(getRoomsByPosition(currentArea,unpack(coords))) > 1 then
set_room(newID)
stretch_map(dir,unpack(coords))
end
if map_mode == "simple" then
local x,y,z = unpack(coords)
local dx,dy,dz,rooms
for k,v in ipairs(exits) do
if v ~= dir then
dx,dy,dz = unpack(coordmap[stubmap[v]])
rooms = getRoomsByPosition(currentArea,x+dx,y+dy,z+dz)
if table.size(rooms) == 1 then
connect_rooms(newID,rooms[0],v)
end
end
end
end
set_room(newID)
end
end
local function find_area_limits(areaID)
-- used to find min and max coordinate limits for an area
if not areaID then error("Find Limits: Missing area ID",2) end
local rooms = getAreaRooms(areaID)
local minx, miny, minz = getRoomCoordinates(rooms[0])
local maxx, maxy, maxz = minx, miny, minz
local x,y,z
for k,v in pairs(rooms) do
x,y,z = getRoomCoordinates(v)
minx = math.min(x,minx)
maxx = math.max(x,maxx)
miny = math.min(y,miny)
maxy = math.max(y,maxy)
minz = math.min(z,minz)
maxz = math.max(z,maxz)
end
return minx, maxx, miny, maxy, minz, maxz
end
local function find_link(name, exits, dir, max_distance)
-- search for matching room in desired direction
local x,y,z = getRoomCoordinates(currentRoom)
if mapping and x then
local dx,dy,dz = unpack(coordmap[stubmap[dir]])
local minx, maxx, miny, maxy, minz, maxz = find_area_limits(currentArea)
local rooms, match, stubs
if max_distance then
minx = x - max_distance
maxx = x + max_distance
miny = y - max_distance
maxy = y + max_distance
minz = z - max_distance
maxz = z + max_distance
end
repeat
x = x + dx
y = y + dy
z = z + dz
rooms = getRoomsByPosition(currentArea,x,y,z)
until (x > maxx or x < minx or y > maxy or y < miny or z > maxz or z < minz or not table.is_empty(rooms))
for k,v in pairs(rooms) do
if check_room(v,name,exits) then
match = v
break
end
end
if match then
connect_rooms(currentRoom, match, dir)
set_room(match)
else
x,y,z = getRoomCoordinates(currentRoom)
create_room(name, exits, dir,{x+dx,y+dy,z+dz})
end
end
end
local function get_recall()
table.load(getMudletHomeDir() .. "/map_recalls.dat",map.recall)
return map.recall[map.character]
end
local function move_map()
-- tries to move the map to the next room
local move = table.remove(move_queue,1)
if move or random_move then
local exits = (currentRoom and getRoomExits(currentRoom)) or {}
local special = (currentRoom and getSpecialExitsSwap(currentRoom)) or {}
if move and not exits[move] and not special[move] then
for k,v in pairs(special) do
if string.starts(k,move) then
move = k
break
end
end
end
if find_portal then
map.find_me(currentName,currentExits,move)
find_portal = false
elseif move == "recall" then
set_room(get_recall())
else
if exits[move] and (vision_fail or check_room(exits[move], currentName, currentExits)) then
set_room(exits[move])
elseif special[move] and (vision_fail or check_room(special[move], currentName, currentExits)) then
set_room(special[move])
elseif not vision_fail then
if mapping and move then
find_link(currentName, currentExits, move)
else
map.find_me(currentName,currentExits, move)
end
end
end
vision_fail = false
end
end
local function capture_move_cmd(dir)
-- captures valid movement commands
dir = string.lower(dir)
if dir == "/" then dir = "recall" end
if table.contains(exitmap,dir) or string.starts(dir,"enter ") or dir == "recall" then
table.insert(move_queue,exitmap[dir] or dir)
elseif currentRoom then
local special = getSpecialExitsSwap(currentRoom) or {}
if special[dir] then table.insert(move_queue,dir) end
end
end
local function capture_room_info(name, exits)
-- captures room info, and tries to move map to match
if (not vision_fail) and name and exits then
prevName = currentName
prevExits = currentExits
name = string.trim(name)
currentName = name
exits = string.gsub(exits,"and","")
currentExits = (exits ~= "" and string.split(exits,"[, ]+")) or {}
move_map()
elseif vision_fail then
move_map()
end
end
local function find_area(name)
-- searches for the named area, and creates it if necessary
local areas = getAreaTable()
local areaID
for k,v in pairs(areas) do
if string.lower(name) == string.lower(k) then
areaID = v
break
end
end
if not areaID then areaID = addAreaName(name) end
if not areaID then error("Invalid Area. No such area found, and area could not be added.") end
currentArea = areaID
end
function map.load_map(use_local)
local path = getMudletHomeDir() .. "/map.dat"
if use_local then
loadMap(path)
print("Map reloaded from local copy.")
else
local address = map.configs.download_path .. "map.dat"
downloading = true
downloadFile(path,address)
print("Downloading Map File.")
end
end
function map.set_exit(dir,roomID)
-- used to set unusual exits from the room you are standing in
if mapping then
roomID = assert(tonumber(roomID),"Set Exit: Invalid Room ID")
if not table.contains(exitmap,dir) then error("Set Exit: Invalid Direction") end
dir = short[exitmap[dir] or dir]
setExit(currentRoom,roomID,dir)
end
end
function map.find_path(roomName,areaName,return_tables)
areaName = (areaName ~= "" and areaName) or nil
local rooms = find_room(roomName,areaName)
local found,dirs = false,{}
local path = {}
for k,v in pairs(rooms) do
found = getPath(currentRoom,k)
if found and (#dirs == 0 or #dirs > #speedWalkDir) then
dirs = speedWalkDir
path = speedWalkPath
end
end
if return_tables then
if table.is_empty(path) then
path, dirs = nil, nil
end
return path, dirs
else
if #dirs > 0 then
print("Path to " .. roomName .. ((areaName and " in " .. areaName) or "") .. ": " .. table.concat(dirs,", "))
else
print("No path found to " .. roomName .. ((areaName and " in " .. areaName) or "") .. ".")
end
end
end
function map.export_area(name)
-- used to export a single area to a file
local areas = getAreaTable()
name = string.lower(name)
for k,v in pairs(areas) do
if name == string.lower(k) then name = k end
end
if not areas[name] then error("No such area.") end
local rooms = getAreaRooms(areas[name])
local tmp = {}
for k,v in pairs(rooms) do
tmp[v] = v
end
rooms = tmp
local tbl = {}
tbl.name = name
tbl.rooms = {}
tbl.exits = {}
tbl.special = {}
local rname, exits, stubs, doors, special, portals, door_up, door_down, coords
for k,v in pairs(rooms) do
rname = getRoomName(v)
exits = getRoomExits(v)
stubs = getExitStubs(v)
doors = getDoors(v)
door_up = getRoomUserData(v,"door up")
door_down = getRoomUserData(v,"door down")
special = getSpecialExitsSwap(v)
portals = getRoomUserData(v,"portals")
coords = {getRoomCoordinates(v)}
tbl.rooms[v] = {name = rname, coords = coords, exits = exits, stubs = stubs, doors = doors, door_up = door_up, door_down = door_down, special = special, portals = portals}
tmp = {}
for k1,v1 in pairs(exits) do
if not table.contains(rooms,v1) then
tmp[k1] = {v1, getRoomName(v1)}
end
end
if not table.is_empty(tmp) then
tbl.exits[v] = tmp
end
tmp = {}
for k1,v1 in pairs(special) do
if not table.contains(rooms,v1) then
tmp[k1] = {v1, getRoomName(v1)}
end
end
if not table.is_empty(tmp) then
tbl.special[v] = tmp
end
end
local path = getMudletHomeDir().."/"..string.gsub(string.lower(name),"%s","_")..".dat"
table.save(path,tbl)
print("Area " .. name .. " exported to " .. path)
end
function map.import_area(name)
name = getMudletHomeDir() .. "/" .. string.gsub(string.lower(name),"%s","_") .. ".dat"
local tbl = {}
table.load(name,tbl)
local areas = getAreaTable()
local areaID = areas[tbl.name] or addAreaName(tbl.name)
local rooms = {}
local ID
for k,v in pairs(tbl.rooms) do
ID = createRoomID()
rooms[k] = ID
addRoom(ID)
setRoomName(ID,v.name)
setRoomArea(ID,areaID)
setRoomCoordinates(ID,unpack(v.coords))
if type(v.stubs) == "table" then
for i,j in pairs(v.stubs) do
setExitStub(ID,j,true)
end
end
for i,j in pairs(v.doors) do
setDoor(ID,i,j)
end
setRoomUserData(ID,"door up",v.door_up)
setRoomUserData(ID,"door down",v.door_down)
setRoomUserData(ID,"portals",v.portals)
end
for k,v in pairs(tbl.rooms) do
for i,j in pairs(v.exits) do
if rooms[j] then
-- print("Setting Exit " .. rooms[k] .. " " .. rooms[j] .. " " .. i)
connect_rooms(rooms[k],rooms[j],i)
end
end
for i,j in pairs(v.special) do
if rooms[j] then
addSpecialExit(rooms[k],rooms[j],i)
end
end
end
for k,v in pairs(tbl.exits) do
for i,j in pairs(v) do
if getRoomName(j[1]) == j[2] then
connect_rooms(rooms[k],j[1],i)
end
end
end
for k,v in pairs(tbl.special) do
for i,j in pairs(v) do
addSpecialExit(k,j[1],i)
end
end
map.fix_portals()
print("Area " .. tbl.name .. " imported from " .. name)
end
function map.set_recall()
-- assigned the current room to be recall for the current character
map.recall[map.character] = currentRoom
table.save(getMudletHomeDir() .. "/map_recalls.dat",map.recall)
print("Recall room set to: " .. getRoomName(currentRoom) .. ".")
end
function map.set_portal(name)
-- creates a new portal in the room
if mapping then
find_portal = name
move_queue = {name}
send(name)
end
end
function map.set_mode(mode)
-- switches mapping modes
if not table.contains({"simple","normal","complex"},mode) then error("Invalid Map Mode, must be 'simple', 'normal', or 'complex'.") end
map_mode = mode
print("Current mode set to: " .. mode)
end
function map.start_mapping(area_name)
-- starts mapping, and sets the current area to the given one, or uses the current one
if not currentName then error("No room detected!") end
local rooms
move_queue = {}
area_name = area_name ~= "" and area_name or nil
if currentArea and not area_name then
local areas = getAreaTableSwap()
area_name = areas[currentArea]
end
if not area_name then print("Start Mapping Error: No area set!") return end
print("Now mapping in area: " .. area_name)
mapping = true
find_area(area_name)
rooms = find_room(currentName, currentArea)
if table.is_empty(rooms) then
if currentRoom then
map.set_area(area_name)
else
create_room(currentName, currentExits, nil, {0,0,0})
end
elseif currentRoom and currentArea ~= getRoomArea(currentRoom) then
map.set_area(area_name)
end
end
function map.stop_mapping()
mapping = false
print("Mapping off.")
end
function map.clear_moves()
move_queue = {}
print("Move queue cleared.")
end
function map.set_area(name)
-- assigns the current room to the area given, creates the area if necessary
if mapping then
find_area(name)
if currentRoom and getRoomArea(currentRoom) ~= currentArea then
setRoomArea(currentRoom,currentArea)
set_room(currentRoom)
end
end
end
function map.set_door(dir,status,one_way)
-- adds a door on a given exit
if mapping then
if not currentRoom then error("Make Door: No room found.") end
dir = exitmap[dir] or dir
if not stubmap[dir] then error("Make Door: Invalid direction.") end
status = (status ~= "" and status) or "closed"
one_way = (one_way ~= "" and one_way) or "no"
if not table.contains({"yes","no"},one_way) then error("Make Door: Invalid one-way status, must be yes or no.") end
local exits = getRoomExits(currentRoom)
local target_room = exits[dir]
if target_room then
exits = getRoomExits(target_room)
end
if one_way == "no" and (target_room and exits[reverse_dirs[dir]] == currentRoom) then
add_door(target_room,reverse_dirs[dir],status)
end
add_door(currentRoom,dir,status)
end
end
function map.shift_room(dir)
-- shifts a room around on the map
if mapping then
dir = assert(exitmap[dir] or (table.contains(exitmap,dir) and dir),"Exit Not Found")
local x,y,z = getRoomCoordinates(currentRoom)
dir = stubmap[dir]
local coords = coordmap[dir]
x = x + coords[1]
y = y + coords[2]
z = z + coords[3]
setRoomCoordinates(currentRoom,x,y,z)
centerview(currentRoom)
end
end
local function check_link(firstID, secondID, dir)
-- check to see if two rooms are connected in a given direction
if not firstID then error("Check Link Error: No first ID",2) end
if not secondID then error("Check Link Error: No second ID",2) end
local name = getRoomName(firstID)
local exits1 = table.union(getRoomExits(firstID),getRoomStubs(firstID))
local exits2 = table.union(getRoomExits(secondID),getRoomStubs(secondID))
local checkID = exits2[reverse_dirs[dir]]
local exits = {}
for k,v in pairs(exits1) do
table.insert(exits,k)
end
return checkID and check_room(checkID,name,exits)
end
function map.find_me(name, exits, dir)
-- tries to locate the player using the current room name and exits, and if provided, direction of movement
-- if direction of movement is given, narrows down possibilities using previous room info
if move ~= "recall" then move_queue = {} end
local check = dir and currentRoom and table.contains(exitmap,dir)
name = name or currentName
exits = exits or currentExits
local rooms = find_room(name)
local match_IDs = {}
for k,v in pairs(rooms) do
if check_room(k, name, exits) then
table.insert(match_IDs,k)
end
end
rooms = match_IDs
match_IDs = {}
if table.size(rooms) > 1 and check then
for k,v in pairs(rooms) do
if check_link(currentRoom,v,dir) then
table.insert(match_IDs,v)
end
end
elseif random_move then
for k,v in pairs(getRoomExits(currentRoom)) do
if check_room(v,currentName,currentExits) then
table.insert(match_IDs,v)
end
end
end
if table.size(match_IDs) == 0 then
match_IDs = rooms
end
if not table.is_empty(match_IDs) and not find_portal then
set_room(match_IDs[1])
elseif find_portal then
if not table.is_empty(match_IDs) then
print("FOUND PORTAL DESTINATION, LINKING ROOMS")
addSpecialExit(currentRoom,match_IDs[1],find_portal)
local portals = getRoomUserData(match_IDs[1],"portals")
portals = portals .. "," .. tostring(currentRoom)..":"..find_portal
setRoomUserData(match_IDs[1],"portals",portals)
set_room(match_IDs[1])
else
print("CREATING PORTAL DESTINATION")
create_room(currentName, currentExits, nil, {getRoomCoordinates(currentRoom)})
end
else
-- for k,v in pairs(rooms) do
-- display(check_room(k,name,exits))
-- if check then display(check_link(currentRoom,k,dir)) end
-- end
-- error("ROOM NOT FOUND!")
end
end
function map.fix_portals()
if mapping then
-- used to clear and update data for portal back-referencing
local rooms = getRooms()
local portals
for k,v in pairs(rooms) do
setRoomUserData(k,"portals","")
end
for k,v in pairs(rooms) do
for cmd,room in pairs(getSpecialExitsSwap(k)) do
portals = getRoomUserData(room,"portals")
if portals ~= "" then portals = portals .. "," end
portals = portals .. tostring(k) .. ":" .. cmd
setRoomUserData(room,"portals",portals)
--print(room,portals)
end
end
end
end
function map.merge_rooms()
-- used to combine essentially identical rooms with the same coordinates
-- typically, these are generated due to mapping errors
if mapping then
local x,y,z = getRoomCoordinates(currentRoom)
local rooms = getRoomsByPosition(currentArea,x,y,z)
local exits, portals,room,cmd,curportals
for k,v in pairs(rooms) do
if v ~= currentRoom then
if getRoomName(v) == getRoomName(currentRoom) then
for k1,v1 in pairs(getRoomExits(v)) do
setExit(currentRoom,v1,stubmap[k1])
exits = getRoomExits(v1)
if exits[reverse_dirs[k1]] == v then
setExit(v1,currentRoom,stubmap[reverse_dirs[k1]])
end
end
for k1,v1 in pairs(getDoors(v)) do
setDoor(currentRoom,k1,v1)
end
for k1,v1 in pairs(getSpecialExitsSwap(v)) do
addSpecialExit(currentRoom,v1,k1)
end
portals = getRoomUserData(v,"portals")
if portals ~= "" then
portals = string.split(portals,",")
for k1,v1 in ipairs(portals) do
room,cmd = unpack(string.split(v1,":"))
addSpecialExit(tonumber(room),currentRoom,cmd)
curportals = getRoomUserData(currentRoom,"portals")
if not string.find(curportals,room) then
curportals = curportals .. "," .. room .. ":" .. cmd
setRoomUserData(currentRoom,"portals",curportals)
end
end
end
if getRoomUserData(v,"door up") ~= "" then
setRoomUserData(currentRoom,"door up",getRoomUserData(v,"door up"))
end
if getRoomUserData(v,"door down") ~= "" then
setRoomUserData(currentRoom,"door down",getRoomUserData(v,"door down"))
end
deleteRoom(v)
end
end
end
end
end
function map.eventHandler(event,...)
if event == "onPrompt" and room_detected then
room_detected = false
capture_room_info(map.prompt.room, map.prompt.exits)
elseif event == "onMoveFail" then
table.remove(move_queue,1)
elseif event == "onVisionFail" then
vision_fail = true
room_detected = true
elseif event == "onRandomMove" then
random_move = true
move_queue = {}
elseif event == "onNewRoom" then
room_detected = true
elseif event == "sysDataSendRequest" then
capture_move_cmd(arg[1])
elseif event == "sysDownloadDone" and downloading then
loadMap(getMudletHomeDir() .. "/map.dat")
downloading = false
print("Map File Loaded.")
elseif event == "sysConnectionEvent" then
config()
end
end
registerAnonymousEventHandler("sysDownloadDone", "map.eventHandler")
registerAnonymousEventHandler("sysConnectionEvent", "map.eventHandler")
registerAnonymousEventHandler("sysDataSendRequest", "map.eventHandler")
registerAnonymousEventHandler("onPrompt", "map.eventHandler")
registerAnonymousEventHandler("onLine"," map.eventHandler")
registerAnonymousEventHandler("onMoveFail"," map.eventHandler")
registerAnonymousEventHandler("onVisionFail"," map.eventHandler")
registerAnonymousEventHandler("onRandomMove"," map.eventHandler")
registerAnonymousEventHandler("onNewRoom"," map.eventHandler")
Re: Mapper Script for New Worlds Ateraan?
I have made some improvements to the script posted here, but since this script is potentially more broadly useful than just for your game, I have the most updated version in its own dedicated thread, found here. In particular, I added some special code to handle doors for in/out exits that did not exist previously, so if this is important in your game, I recommend checking it out.
Re: Mapper Script for New Worlds Ateraan?
Hey. I really appreciate all your help. You taking the time to keep up with me has been great. Thanks for everything. I haven't gotten into this yet, but I'll probably be checking it out when I get home tonight.
Re: Mapper Script for New Worlds Ateraan?
Have a look at the cmud map importer as well, it might or might not work: http://forums.mudlet.org/viewtopic.php?f=6&t=2274.