local MINIMAP_DEFAULT_RADIUS = 1000 * FRACUNIT local MINIMAP_DEFAULT_SIZE = 40 local DEFAULT_LINE_STEP = 20 COM_AddCommand("mm_radius", function(p, arg) if not (p.minimap) then return end if (tonumber(arg) ~= nil) then p.minimap.radius = min(max(200, tonumber(arg)), 1600) * FRACUNIT else CONS_Printf(p, "Please insert a valid number.(Min: 200, Max: 1600)\nWarning! High values may cause frame drops!") end end) COM_AddCommand("mm_hudsize", function(p, arg) if not (p.minimap) then return end if (tonumber(arg) ~= nil) then p.minimap.size = min(max(10, tonumber(arg)), 160) else CONS_Printf(p, "Please insert a valid number.(Min: 10, Max: 160)") end end) COM_AddCommand("mm_drawcount", function (p, arg) if not (p.minimap) then return end if (tonumber(arg) ~= nil) then p.minimap.linestep = min(max(5, tonumber(arg)), 80) else CONS_Printf(p, "Please insert a valid number.(Min: 5, Max: 80)\nWarning! High values may cause frame drops!") end end) COM_AddCommand("mm_fixed", function (p, arg) if not (p.minimap) then return end if (tonumber(arg) ~= nil) then p.minimap.pointnorth = (tonumber(arg) > 0 and false) or true else CONS_Printf(p, "Please insert a valid number.(0/1)") end end) COM_AddCommand("mm_corner", function (p, arg) if not (p.minimap) then return end if (arg == "tl" or arg == "tr" or arg == "bl" or arg == "br") then p.minimap.corner = arg else CONS_Printf(p, "Please insert a valid corner.(tl/tr/bl/br)") end end) COM_AddCommand("mm_offset", function (p, argx, argy) if not (p.minimap) then return end if (tonumber(argx) ~= nil and tonumber(argy) ~= nil) then p.minimap.offset = {x = tonumber(argx), y = tonumber(argy)} else CONS_Printf(p, "Please insert two valid numbers.") end end) COM_AddCommand("mm_enable", function (p, arg) if not (p.minimap) then return end if (tonumber(arg) ~= nil) then p.minimap.enabled = (tonumber(arg) > 0 and true) or false else CONS_Printf(p, "Please insert a valid number.(0/1)") end end) local function getNearestLines(p) p.minimap.currentlines = {} local found = searchBlockmap("lines", function(mo, line) table.insert(mo.player.minimap.currentlines, line) end, p.mo, p.mo.x - p.minimap.radius, p.mo.x + p.minimap.radius, p.mo.y - p.minimap.radius, p.mo.y + p.minimap.radius ) end local function minimapThink(p) if not p.minimap then p.minimap = { enabled = true, radius = MINIMAP_DEFAULT_RADIUS, size = MINIMAP_DEFAULT_SIZE, linestep = DEFAULT_LINE_STEP, offset = {x = 0, y = 0}, corner = "tr", pointnorth = false, currentlines = {} } end if not (p.minimap.enabled) then return end getNearestLines(p) end addHook("PlayerThink", minimapThink) local function realDistToMinimap(p, line) local fuPerPixel = (p.minimap.radius * 2 / p.minimap.size) local v1x = p.mo.x - line.v1.x local v1y = p.mo.y - line.v1.y local v1screenx = FixedInt(FixedDiv(v1x, fuPerPixel)) local v1screeny = FixedInt(FixedDiv(v1y, fuPerPixel)) local v2x = p.mo.x - line.v2.x local v2y = p.mo.y - line.v2.y local v2screenx = FixedInt(FixedDiv(v2x, fuPerPixel)) local v2screeny = FixedInt(FixedDiv(v2y, fuPerPixel)) return v1screenx, v1screeny, v2screenx, v2screeny end local function realDistToMinimapPlayer(p, p2) local fuPerPixel = (p.minimap.radius * 2 / p.minimap.size) local px = p.mo.x - p2.mo.x local py = p.mo.y - p2.mo.y local pscreenx = FixedInt(FixedDiv(px, fuPerPixel)) local pscreeny = FixedInt(FixedDiv(py, fuPerPixel)) return pscreenx, pscreeny end local function getLineAngles(p, line) local turnangle = (p.cmd.angleturn << 16) + ANGLE_90 local angv1 = R_PointToAngle2(p.mo.x, p.mo.y, line.v1.x, line.v1.y) - turnangle local angv2 = R_PointToAngle2(p.mo.x, p.mo.y, line.v2.x, line.v2.y) - turnangle return angv1, angv2 end local function getPlayerAngle(p, p2) local turnangle = (p.cmd.angleturn << 16) + ANGLE_90 local ang = R_PointToAngle2(p.mo.x, p.mo.y, p2.mo.x, p2.mo.y) - turnangle return ang end local function rotateVertexPosition(vx, vy, ang) local dist = R_PointToDist2(0, 0, vx * FRACUNIT, vy * FRACUNIT) local newvx = FixedInt(FixedMul(cos(ang), dist)) local newvy = FixedInt(FixedMul(sin(ang), dist)) return newvx, newvy end local function minimapDraw(v, p, cam) if not (p.minimap) then return end if not (p.minimap.enabled) then return end local resolutionwidth = v.width() / v.dupx() local resolutionheight = v.height() / v.dupy() local x, y local flags if (p.minimap.corner == "tr") then x = (resolutionwidth - (10 + p.minimap.offset.x)) - p.minimap.size y = 10 + p.minimap.offset.y flags = V_SNAPTORIGHT | V_SNAPTOTOP if (splitscreen and p == secondarydisplayplayer) then y = $ + resolutionheight / 2 end elseif (p.minimap.corner == "tl") then x = 10 + p.minimap.offset.x y = 10 + p.minimap.offset.y flags = V_SNAPTOLEFT | V_SNAPTOTOP if (splitscreen and p == secondarydisplayplayer) then y = $ + resolutionheight / 2 end elseif (p.minimap.corner == "br") then x = (resolutionwidth - (10 + p.minimap.offset.x)) - p.minimap.size y = (resolutionheight - (10 + p.minimap.offset.y)) - p.minimap.size flags = V_SNAPTORIGHT | V_SNAPTOBOTTOM if (splitscreen and p == displayplayer) then y = $ - resolutionheight / 2 end elseif (p.minimap.corner == "bl") then x = 10 + p.minimap.offset.x y = (resolutionheight - (10 + p.minimap.offset.y)) - p.minimap.size flags = V_SNAPTOLEFT | V_SNAPTOBOTTOM if (splitscreen and p == displayplayer) then y = $ - resolutionheight / 2 end end local px = x + p.minimap.size / 2 local py = y + p.minimap.size / 2 v.drawFill(x, y, p.minimap.size, p.minimap.size, 31 | flags) v.drawFill(px, py, 1, 1, 166 | flags) for k, line in ipairs(p.minimap.currentlines) do local v1x, v1y, v2x, v2y = realDistToMinimap(p, line) if not (p.minimap.pointnorth) then local angv1, angv2 = getLineAngles(p, line) v1x, v1y = rotateVertexPosition(v1x, v1y, angv1) v2x, v2y = rotateVertexPosition(v2x, v2y, angv2) end for i = 0, p.minimap.linestep do local xdiff = (v2x - v1x) * i / p.minimap.linestep local ydiff = (v2y - v1y) * i / p.minimap.linestep local drawstartx = px - (v1x + xdiff) local drawstarty = py + (v1y + ydiff) if ((drawstartx >= x + p.minimap.size) or (drawstartx < x) or (drawstarty >= y + p.minimap.size) or (drawstarty < y)) then continue end local linecolor = 8 if (line.flags & ML_IMPASSIBLE) then linecolor = 1 elseif (line.frontside ~= nil and line.backside ~= nil) then --doublesided means on the same floor level, probably linecolor = 16 end v.drawFill(drawstartx, drawstarty, 1, 1, linecolor | flags) end end for pl in players.iterate do if p == pl then continue end local plx, ply = realDistToMinimapPlayer(p, pl) if not (p.minimap.pointnorth) then local ang = getPlayerAngle(p, pl) plx, ply = rotateVertexPosition(plx, ply, ang) end local drawstartx = px - plx local drawstarty = py + ply if ((drawstartx >= x + p.minimap.size) or (drawstartx < x) or (drawstarty >= y + p.minimap.size) or (drawstarty < y)) then continue end local cmap = v.getColormap(pl.mo.skin, pl.skincolor) local index = cmap[skins[pl.mo.skin].starttranscolor + 8] v.drawFill(drawstartx, drawstarty, 1, 1, index | flags) end end hud.add(minimapDraw, "game")