Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Custom item: Automap v0.2 FINAL.
- -- Created by Parallax, November 2007.
- -- Extremely minor fixes by Sophia, May 2012.
- -- Thanks to Joramun, whose magic map was an invaluable reference in the early stages of development.
- -- Thanks to Sophia for DSB, as well as for her help and advice.
- -- Thanks to Gambit37, whose beautiful Conflux maps inspired the default background.
- -- This item was designed with modularity and adaptability in mind. Some comments are interspersed throughout the code
- -- to try and make the process a little bit more transparent. I hope they help.
- -- Feel free to use this item as is in your own dungeon and to modify it to suit your needs. If you do use it, please
- -- acknowledge me in the credits.
- gfx[ROOT_NAME .. "_background"] = dsb_get_bitmap("Automap_backgd")
- if (not esb_typecheck) then
- local iconsheet = dsb_get_bitmap("Automap_tiles")
- gfx[ROOT_NAME .. "_tiles"] = {}
- local counter = 0
- for y=0,(dsb_bitmap_height(iconsheet)-15),15 do
- for x=0,(dsb_bitmap_width(iconsheet)-15),15 do
- gfx[ROOT_NAME .. "_tiles"][counter] = dsb_new_bitmap(15, 15)
- dsb_bitmap_blit(iconsheet, gfx[ROOT_NAME .. "_tiles"][counter], x, y, 0, 0, 15, 15)
- counter = counter + 1
- end
- end
- dsb_destroy_bitmap(iconsheet)
- end
- if (not esb_typecheck) then
- iconsheet = dsb_get_bitmap("Automap_arrow")
- gfx[ROOT_NAME .. "_arrow"] = {}
- local counter = 0
- for x=0,(dsb_bitmap_width(iconsheet)-15),15 do
- gfx[ROOT_NAME .. "_arrow"][counter] = dsb_new_bitmap(15, 15)
- dsb_bitmap_blit(iconsheet, gfx[ROOT_NAME .. "_arrow"][counter], x, 0, 0, 0, 15, 15)
- counter = counter + 1
- end
- dsb_destroy_bitmap(iconsheet)
- end
- -- This function draws a quarter of a closed tile (or unexplored fake wall) and a selection of wallitems on it.
- -- The contents of this function can be altered to change what wallitems get displayed.
- function automap_drawpartial(map, tile, FLAG, lvl, x, y, dir, ptx, pty)
- local i
- local item
- local hasaltar = false
- local hasalcove = false
- local hasfountain = false
- local hasmirror = false
- -- Start by drawing a wall.
- dsb_bitmap_draw(tile[FLAG.WALL + dir], map, ptx, pty, false)
- -- Then make a list of every instance on the tile.
- local contents = dsb_fetch(lvl, x, y, dir)
- -- Now go through all instances on the given tile and see if anything else needs displaying.
- if (contents == nil) then return end
- for i in pairs(contents) do
- item = dsb_find_arch(contents[i])
- if ((item.class == "ALCOVE") and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then
- if (item == obj.alcove_vi) then
- hasaltar = true
- else
- hasalcove = true
- end
- end
- if ((item.class == "FOUNTAIN") and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasfountain = true end
- if ((item == obj.mirror) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasmirror = true end
- end
- -- Contents enumerated, now display what needs displaying.
- if (hasaltar) then dsb_bitmap_draw(tile[FLAG.ALTAR + dir], map, ptx, pty, false) end
- if (hasalcove) then dsb_bitmap_draw(tile[FLAG.ALCOV + dir], map, ptx, pty, false) end
- if (hasfountain) then dsb_bitmap_draw(tile[FLAG.FOUNT + dir], map, ptx, pty, false) end
- if (hasmirror) then dsb_bitmap_draw(tile[FLAG.MIRRO + dir], map, ptx, pty, false) end
- return
- end
- -- This function draws the open (or closed, visited, movable wall) tile at (lvl, x, y) in the dungeon.
- -- The graphics are drawn on {map} at the coordinates (ptx, pty) and are taken from the tile set {tile}.
- -- You may want to modifiy this function to change what gets displayed on the automap.
- -- If you want to change the background image, or the tile set or you want fake walls to be revealed
- -- by standing next to them, this is not the right place.
- function automap_drawfull(map, tile, FLAG, lvl, x, y, ptx, pty)
- local i
- local item
- local hasup = false
- local hasdown = false
- local hasframe = false
- local way
- local hasdoorbutton = false
- local hasdoor = false
- local thedoor
- local hasfake = false
- local haspit = false
- local hashaze = false
- local haspad = false
- local hasfirepit = false
- local hassquaredrain = false
- local hasrounddrain = false
- -- Start by drawing an open tile.
- dsb_bitmap_draw(tile[FLAG.FLOOR], map, ptx, pty, false)
- -- Then check for wall. Closed movable walls get nothing else.
- if (dsb_get_cell(lvl, x, y) ~= false) then
- dsb_bitmap_draw(tile[FLAG.BLOCK], map, ptx, pty, false)
- return
- end
- -- Then make a list of every instance on the tile.
- local contents = dsb_fetch(lvl, x, y, CENTER)
- -- Now go through all instances on the given tile and see if anything else needs displaying.
- if (contents == nil) then return end
- for i in pairs(contents) do
- item = dsb_find_arch(contents[i])
- if ((item == obj.fakewall) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasfake = true end
- if ((item == obj.stairsdown) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasdown = true end
- if ((item == obj.stairsup) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasup = true end
- if ((item == obj.fakepit) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then haspit = true end
- if ((item == obj.pit) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then haspit = true end
- if ((item == obj.doorframe) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then
- -- There is a doorframe, but we need to know whether to display it north-south
- -- or east-west. Since doors may be completely surrounded by walls, looking at
- -- walls around may cause graphical glitches. We look for visited tiles instead.
- if (dsb_visited(lvl,x+1,y) or dsb_visited(lvl,x-1,y)) then
- hasframe = true
- way = 1
- elseif (dsb_visited(lvl,x,y+1) or dsb_visited(lvl,x,y-1)) then
- hasframe = true
- way = 0
- end
- -- We might end up here with way undefined if the party has been teleported or dropped onto
- -- a tile with a door frame. In that case well, tough luck, we're not displaying anything.
- end
- if ((item == obj.doorbutton) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasdoorbutton = true end
- if ((item.type == "DOOR") and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then
- hasdoor = true
- thedoor = dsb_find_arch(contents[i])
- if (dsb_get_gfxflag(contents[i], GF_BASHED)) then hasdoor = false end
- end
- if ((item == obj.bluehaze) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hashaze = true end
- if ((item == obj.pad) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then haspad = true end
- if ((item == obj.firepit) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasfirepit = true end
- if ((item == obj.squaredrain) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hassquaredrain = true end
- if ((item == obj.rounddrain) and (not dsb_get_gfxflag(contents[i], GF_INACTIVE))) then hasrounddrain = true end
- end
- -- Fake walls take precedence over stairs but neither displays anything else.
- if (hasfake) then
- dsb_bitmap_draw(tile[FLAG.FAKE], map, ptx, pty, false)
- return
- end
- if (hasup) then
- dsb_bitmap_draw(tile[FLAG.GO_UP], map, ptx, pty, false)
- return
- end
- if (hasdown) then
- dsb_bitmap_draw(tile[FLAG.GO_DN], map, ptx, pty, false)
- return
- end
- -- Other objects are compatible.
- if (haspit) then dsb_bitmap_draw(tile[FLAG.PIT], map, ptx, pty, false) end
- if (haspad) then dsb_bitmap_draw(tile[FLAG.PAD], map, ptx, pty, false) end
- if (hasfirepit) then dsb_bitmap_draw(tile[FLAG.FIRE], map, ptx, pty, false) end
- if (hassquaredrain) then dsb_bitmap_draw(tile[FLAG.SQDRN], map, ptx, pty, false) end
- if (hasrounddrain) then dsb_bitmap_draw(tile[FLAG.RDDRN], map, ptx, pty, false) end
- if (hasframe) then
- if (hasdoorbutton) then dsb_bitmap_draw(tile[FLAG.DBUTT+way], map, ptx, pty, false) end
- if (hasdoor) then
- if (thedoor.class == "WOOD") then
- dsb_bitmap_draw(tile[FLAG.DWOOD+way], map, ptx, pty, false)
- elseif (thedoor.class == "PORTCULLIS") then
- dsb_bitmap_draw(tile[FLAG.DPORT+way], map, ptx, pty, false)
- elseif (thedoor.class == "METAL") then
- dsb_bitmap_draw(tile[FLAG.DMETL+way], map, ptx, pty, false)
- elseif (thedoor.class == "BLACK") then
- dsb_bitmap_draw(tile[FLAG.DBLAK+way], map, ptx, pty, false)
- elseif (thedoor.class == "RA") then
- dsb_bitmap_draw(tile[FLAG.DRA+way], map, ptx, pty, false)
- else
- dsb_bitmap_draw(tile[FLAG.DWOOD+way], map, ptx, pty, false)
- end
- else
- dsb_bitmap_draw(tile[FLAG.FRAME+way], map, ptx, pty, false)
- end
- end
- if (hashaze) then dsb_bitmap_draw(tile[FLAG.HAZE], map, ptx, pty, false) end
- return
- end
- -- This is the general automap display function. It selects the appropriate images, computes the range of display and
- -- cycles through all tiles to see if they should be displayed.
- -- If you wish to change the background image or the tile set, look in here.
- -- If you want to make fake walls visible on the map even when they have not been stepped on, it's in here too.
- -- To display more or other wallitems, modify the MAP_FLAG table(s) and the function autmap_drawpartial above.
- -- If you want to change what gets displayed on the open tiles, alter MAP_FLAG and look in automap_drawfull above.
- function automap_display(bitmap, mouse_x, mouse_y)
- local lev, party_x, party_y, facing = dsb_party_coords()
- -- What follows here is a horrible, terrible hack to recover the name of the archetype that launched the fullscreen
- -- function because we cannot assume that it will be "automap", and we need to know it for sure in order to access
- -- the graphics. The item that launched this fullscreen, our automap, can only be in one of five locations: mouse
- -- pointer, or one of the four party right hands. We check every location for an item for which the 'marker' value
- -- matches the "key", an unremarkable 39-digit hexadecimal number.
- -- This method is NOT foolproof. While the probability that another, unrelated archetype would have the same value
- -- for the nonstandard property 'marker' is astronomically low, the chances that someone would clone this automap
- -- and not change the value of 'marker' are fairly high. And that is bound to cause trouble.
- local ppos
- local self_arch
- local check_arch
- local check = dsb_fetch(MOUSE_HAND, 0, 0, 0)
- if (check ~= nil) then check_arch = dsb_find_arch(check) end
- if (check_arch ~= nil) then
- if (check_arch.marker == "F10C16FD355D1A7A93C0A9178BD95F468285F9") then self_arch = check_arch end
- end
- for ppos=0, 3 do
- if (dsb_ppos_char(ppos)) then
- check = dsb_fetch(PARTY, ppos, INV_R_HAND, 0)
- if (check ~= nil) then
- check_arch = dsb_find_arch(check)
- if (check_arch ~= nil) then
- if (check_arch.marker == "F10C16FD355D1A7A93C0A9178BD95F468285F9") then self_arch = check_arch end
- end
- end
- end
- end
- -- If using multiple maps, replace these parameters with a function
- -- that selects the map and tileset you want to use based on the party's position.
- -- The map is drawn on bitmap background, using the tile set tile_set. Only the rectangle from (left, top) to
- -- (right, bottom) will have tiles drawn on. The party is represented by {arrow}.
- local left = 122
- local top = 74
- local right = 482
- local bottom = 434
- local tile_set = self_arch.tiles
- local background = self_arch.backgd
- local arrow = self_arch.arrow
- local MAP_FLAG = { VOID = 0, -- Pink square for undefined items.
- FLOOR = 1, -- Open tile. shows the ground.
- GO_UP = 2, -- Stairs going up.
- GO_DN = 3, -- Stairs going down.
- WALL = 4, -- Solid wall, Northern face. East is +1, South +2, West +3.
- OPEN = 8, -- Partial open tile, northern face. Once again, the next three indexes are reserved for the other directions.
- BLOCK = 12, -- Closed movable wall the tile of which was once stepped on while open.
- FAKE = 13, -- Fake wall that has been visited.
- PIT = 14, -- Fake or real pit. Not invisible pit.
- HAZE = 15, -- Blue haze.
- FRAME = 16, -- Door frame. Used for open doors as well.
- DWOOD = 18, -- Closed wooden door.
- DPORT = 20, -- Closed portcullis.
- DMETL = 22, -- Closed metal door.
- DBLAK = 24, -- Closed black door.
- DBUTT = 48, -- Door button, for doors that have them.
- DRA = 26, -- Closed RA door.
- PAD = 28, -- Large pad.
- FIRE = 29, -- Black flame fire pit.
- SQDRN = 30, -- Square grate.
- RDDRN = 31, -- Round grate.
- FOUNT = 32, -- Lion head or medusa fountain.
- ALCOV = 36, -- Square or round alcove
- ALTAR = 40, -- VI altar of rebirth.
- MIRRO = 44 -- Champion mirror.
- }
- -- First we draw the background image.
- dsb_bitmap_draw(background, bitmap, 0, 0, false)
- -- Now we compute the display range of the map, which is the largest fraction
- -- of the level that we can display on the map and still have the party position in view.
- -- Within these constraints, the map will center on the party as closely as possible.
- -- Note: NO check is made as to whether this is the most map that could be displayed.
- -- In fully explored levels, both areas would coincide, but not necessary while still exploring.
- local wide = dsb_bitmap_width(tile_set[0])
- local high = dsb_bitmap_height(tile_set[0])
- local xrange = math.floor((right-left+1) / wide)
- local yrange = math.floor((bottom-top+1) / high)
- local xcenter = (right+left)/2
- local ycenter = (top+bottom)/2
- local xmin = -1
- local ymin = -1
- if (party_x-xrange/2>xmin) then xmin = math.floor(party_x-xrange/2) end
- if (party_y-yrange/2>ymin) then ymin = math.floor(party_y-yrange/2) end
- local xmax, ymax = dsb_level_getinfo(lev)
- if (xmin+xrange-1<xmax) then xmax = xmin+xrange-1 end
- if (ymin+yrange-1<ymax) then ymax = ymin+yrange-1 end
- xcenter = math.floor(xcenter - ((xmin+xmax)/2+0.5)*wide + 0.001)
- ycenter = math.floor(ycenter - ((ymin+ymax)/2+0.5)*high + 0.001)
- -- Now that we have the display range and the reference point, we can cycle over the entire display.
- local dir
- local xdiff
- local ydiff
- local drawit
- local contents
- local id
- local item
- local isfake
- for y=ymin, ymax do
- for x=xmin, xmax do
- -- This part draws (or not) the tile at (x,y). If you want a secret
- -- area, insert a controller function here.
- -- compute the screen coordinates for the top-left corner of the tile.
- x_dest = xcenter + x*wide
- y_dest = ycenter + y*high
- -- Check if the tile is a fake wall. Unexplored faked walls will be treated as real walls
- -- so as not to spoil the secrets.
- -- if you DO wish to spoil the secrets, then remove the loop so isfake is always false, and
- -- also remove the similar loop further down.
- isfake = false
- contents = dsb_fetch(lev, x, y, CENTER)
- if (contents ~= nil) then
- for id in pairs(contents) do
- item = dsb_find_arch(contents[id])
- if ((item == obj.fakewall) and (not dsb_get_gfxflag(contents[id], GF_INACTIVE))) then isfake = true end
- end
- end
- -- Now determine if the tile should be drawn entirely, partially, or not at all.
- if (dsb_visited(lev, x, y)) then
- -- tile has been visited, draw it.
- automap_drawfull(bitmap, tile_set, MAP_FLAG, lev, x, y, x_dest, y_dest)
- elseif ((dsb_get_cell(lev, x, y) ~= false) or isfake) then
- -- This tile is a wall, check each side to see if we need to draw it.
- for dir=0, 3 do
- xdiff = 0
- ydiff = 0
- if (dir == 0) then ydiff = -1 end
- if (dir == 1) then xdiff = 1 end
- if (dir == 2) then ydiff = 1 end
- if (dir == 3) then xdiff = -1 end
- -- Check the tile in front of the wall.
- if (dsb_visited(lev, x+xdiff, y+ydiff)) then
- -- It was visited. Draw a wall in that direction.
- automap_drawpartial(bitmap, tile_set, MAP_FLAG, lev, x, y, dir, x_dest, y_dest)
- elseif (dsb_get_cell(lev, x+xdiff, y+ydiff) == false) then
- -- The tile is open, but not visited.
- -- Draw a wall if a visited tile is adjacent.
- drawit = dsb_visited(lev, x+2*xdiff, y+2*ydiff)
- drawit = drawit or dsb_visited(lev, x+xdiff+ydiff, y+ydiff+xdiff)
- drawit = drawit or dsb_visited(lev, x+xdiff-ydiff, y+ydiff-xdiff)
- -- but do not draw if this adjacent tile is a fake wall!
- contents = dsb_fetch(lev, x+xdiff, y+ydiff, CENTER)
- if (contents ~= nil) then
- for id in pairs(contents) do
- item = dsb_find_arch(contents[id])
- if ((item == obj.fakewall) and (not dsb_get_gfxflag(contents[id], GF_INACTIVE))) then drawit = false end
- end
- end
- if (drawit) then
- automap_drawpartial(bitmap, tile_set, MAP_FLAG, lev, x, y, dir, x_dest, y_dest)
- end
- end
- end
- else
- -- This tile is open but not visited. Draw it full if adjacent to a visited tile.
- drawit = dsb_visited(lev, x+1, y)
- drawit = drawit or dsb_visited(lev, x-1, y)
- drawit = drawit or dsb_visited(lev, x, y+1)
- drawit = drawit or dsb_visited(lev, x, y-1)
- if (drawit) then
- automap_drawfull(bitmap, tile_set, MAP_FLAG, lev, x, y, x_dest, y_dest)
- else
- -- OK, so it is not adjacent to a visited tile. Draw a partial open tile
- -- in each direction where it is adjacent to an open tile that is
- -- adjacent to a visited tile (and then we're done, promised!)
- for dir=0, 3 do
- xdiff = 0
- ydiff = 0
- if (dir == 0) then ydiff = -1 end
- if (dir == 1) then xdiff = 1 end
- if (dir == 2) then ydiff = 1 end
- if (dir == 3) then xdiff = -1 end
- -- Check the tile in this direction.
- if (dsb_get_cell(lev, x+xdiff, y+ydiff) == false) then
- -- The tile is open.
- -- Draw a partial open space if a visited tile is adjacent.
- drawit = dsb_visited(lev, x+2*xdiff, y+2*ydiff)
- drawit = drawit or dsb_visited(lev, x+xdiff+ydiff, y+ydiff+xdiff)
- drawit = drawit or dsb_visited(lev, x+xdiff-ydiff, y+ydiff-xdiff)
- if (drawit) then
- dsb_bitmap_draw(tile_set[MAP_FLAG.OPEN+dir], bitmap, x_dest, y_dest, false)
- end
- end
- end
- end
- end
- end
- end
- -- Finally, display the party arrow.
- x_dest = xcenter + party_x*wide
- y_dest = ycenter + party_y*high
- dsb_bitmap_draw(arrow[facing], bitmap, x_dest, y_dest, false)
- return false
- end
- function automap_click(mouse_x, mouse_y, mouse_buttons)
- return true
- end
- function method_view_automap()
- dsb_fullscreen(automap_display, automap_click, nil, nil)
- end
- obj[ROOT_NAME] = {
- name="AUTOMAP",
- type="THING",
- class="SCROLL",
- mass=1,
- icon=gfx.icons[31],
- alt_icon=gfx.icons[30],
- dungeon=gfx.scroll,
- backgd = gfx[ROOT_NAME .. "_background"],
- tiles = gfx[ROOT_NAME .. "_tiles"],
- arrow = gfx[ROOT_NAME .. "_arrow"],
- marker = "F10C16FD355D1A7A93C0A9178BD95F468285F9",
- methods = {
- { "EXAMINE", 0, CLASS_FIGHTER, method_view_automap }
- },
- to_r_hand = alticon,
- from_r_hand = normicon,
- on_look = method_view_automap,
- fit_chest=true
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement