274 lines
8.6 KiB
Lua
274 lines
8.6 KiB
Lua
function init()
|
|
self.modes = {"off", "worldInfo", "rectQuery", "radQuery", "lineQuery", "showCollision", "resolveCollision", "lineCollision"}
|
|
self.mode = 1
|
|
self.radii = {0.5, 1.5, 5}
|
|
self.radius = 2
|
|
self.shapes = {"square", "diamond", "octagon"}
|
|
self.shape = 1
|
|
self.boundModes = {"MetaBoundBox", "CollisionArea", "Position"}
|
|
self.boundMode = 1
|
|
self.entityTypes = {"all", "creature", "mobile", "player", "monster", "npc", "itemDrop", "projectile", "plant", "plantDrop", "effect"}
|
|
self.entityType = 1
|
|
self.collideTolerance = 2
|
|
self.lastMoves = {}
|
|
end
|
|
|
|
function update(args)
|
|
if args.moves["special1"] and not self.lastMoves["special1"] then
|
|
cycleMode()
|
|
elseif args.moves["special2"] and not self.lastMoves["special2"] then
|
|
cycleRadius()
|
|
elseif args.moves["special3"] and not self.lastMoves["special3"] then
|
|
if self.mode == 3 or self.mode == 4 or self.mode == 5 then
|
|
if args.moves["down"] and not self.lastMoves["down"] then
|
|
cycleBoundMode()
|
|
else
|
|
cycleEntityType()
|
|
end
|
|
elseif self.mode == 6 or self.mode == 7 then
|
|
cycleShape()
|
|
end
|
|
end
|
|
|
|
self.lastMoves = args.moves
|
|
|
|
local modeStr = self.modes[self.mode]
|
|
args.aimPosition = tech.aimPosition()
|
|
if modeStr == "worldInfo" then
|
|
doWorldInfo(args)
|
|
elseif modeStr == "rectQuery" then
|
|
doRectQuery(args)
|
|
elseif modeStr == "radQuery" then
|
|
doRadQuery(args)
|
|
elseif modeStr == "lineQuery" then
|
|
doLineQuery(args)
|
|
elseif modeStr == "showCollision" then
|
|
doShowCollision(args)
|
|
elseif modeStr == "resolveCollision" then
|
|
doResolveCollision(args)
|
|
elseif modeStr == "lineCollision" then
|
|
doLineCollision(args)
|
|
end
|
|
|
|
return 0
|
|
end
|
|
|
|
function cycleMode()
|
|
self.mode = (self.mode % #self.modes) + 1
|
|
end
|
|
|
|
function cycleRadius()
|
|
self.radius = (self.radius % #self.radii) + 1
|
|
end
|
|
|
|
function cycleShape()
|
|
self.shape = (self.shape % #self.shapes) + 1
|
|
end
|
|
|
|
function cycleBoundMode()
|
|
self.boundMode = (self.boundMode % #self.boundModes) + 1
|
|
end
|
|
|
|
function cycleEntityType()
|
|
self.entityType = (self.entityType % #self.entityTypes) + 1
|
|
end
|
|
|
|
function doWorldInfo(args)
|
|
local pos = args.aimPosition
|
|
local message = string.format("Position %.3f, %.3f\nGravity %s\nLight %.3f\nWind %s\nFG %s (mod %s)\nBG %s (mod %s)",
|
|
pos[1], pos[2],
|
|
world.gravity(pos),
|
|
world.lightLevel(pos),
|
|
world.windLevel(pos),
|
|
world.material(pos, "foreground"),
|
|
world.mod(pos, "foreground"),
|
|
world.material(pos, "background"),
|
|
world.mod(pos, "background"))
|
|
world.debugPoint(pos, "green")
|
|
world.debugText(message, {pos[1] + 1, pos[2] - 1}, "white")
|
|
end
|
|
|
|
function makeQueryOptions()
|
|
local queryOptions = {
|
|
boundMode = self.boundModes[self.boundMode]
|
|
}
|
|
|
|
if self.entityTypes[self.entityType] ~= "all" then
|
|
queryOptions.includedTypes = {self.entityTypes[self.entityType]}
|
|
end
|
|
|
|
return queryOptions
|
|
end
|
|
|
|
function doRectQuery(args)
|
|
local queryRadius = self.radii[self.radius]
|
|
|
|
local ll = {args.aimPosition[1] - queryRadius, args.aimPosition[2] - queryRadius}
|
|
local ur = {args.aimPosition[1] + queryRadius, args.aimPosition[2] + queryRadius}
|
|
|
|
local entityIds = world.entityQuery(ll, ur, makeQueryOptions())
|
|
|
|
drawDebugRect({ll[1], ll[2], ur[1], ur[2]}, "#7777FF")
|
|
world.debugText(string.format("%s entities (rect, %s, %s)", #entityIds, self.entityTypes[self.entityType], self.boundModes[self.boundMode]), {ll[1], ur[2]}, "white")
|
|
|
|
for _, entityId in pairs(entityIds) do
|
|
world.debugPoint(world.entityPosition(entityId), "green")
|
|
world.debugText(world.entityType(entityId).." "..entityId, world.entityPosition(entityId), "white")
|
|
end
|
|
end
|
|
|
|
function doRadQuery(args)
|
|
local queryRadius = self.radii[self.radius]
|
|
|
|
local entityIds = world.entityQuery(args.aimPosition, queryRadius, makeQueryOptions())
|
|
|
|
drawDebugPoly(makePoly("octagon", queryRadius), "#7777FF", args.aimPosition)
|
|
world.debugText(string.format("%s entities (rad, %s, %s)", #entityIds, self.entityTypes[self.entityType], self.boundModes[self.boundMode]), {args.aimPosition[1] - queryRadius, args.aimPosition[2] + queryRadius}, "white")
|
|
|
|
for _, entityId in pairs(entityIds) do
|
|
world.debugPoint(world.entityPosition(entityId), "green")
|
|
world.debugText(world.entityType(entityId).." "..entityId, world.entityPosition(entityId), "white")
|
|
end
|
|
end
|
|
|
|
function doLineQuery(args)
|
|
local queryRadius = self.radii[self.radius]
|
|
|
|
local ll = {args.aimPosition[1] - queryRadius, args.aimPosition[2] - queryRadius}
|
|
local ur = {args.aimPosition[1] + queryRadius, args.aimPosition[2] + queryRadius}
|
|
|
|
local entityIds = world.entityLineQuery(ll, ur, makeQueryOptions())
|
|
|
|
world.debugLine(ll, ur, "#7777FF")
|
|
world.debugText(string.format("%s entities (line, %s, %s)", #entityIds, self.entityTypes[self.entityType], self.boundModes[self.boundMode]), {ll[1], ur[2]}, "white")
|
|
|
|
for _, entityId in pairs(entityIds) do
|
|
world.debugPoint(world.entityPosition(entityId), "green")
|
|
world.debugText(world.entityType(entityId).." "..entityId, world.entityPosition(entityId), "white")
|
|
end
|
|
end
|
|
|
|
function doShowCollision(args)
|
|
local polyRadius = self.radii[self.radius]
|
|
local polyShape = self.shapes[self.shape]
|
|
local collidePoly = makePoly(polyShape, polyRadius)
|
|
|
|
local colliding = world.polyCollision(collidePoly, args.aimPosition)
|
|
|
|
if colliding then
|
|
drawDebugPoly(collidePoly, "red", args.aimPosition)
|
|
else
|
|
drawDebugPoly(collidePoly, "green", args.aimPosition)
|
|
end
|
|
end
|
|
|
|
function doResolveCollision(args)
|
|
local polyRadius = self.radii[self.radius]
|
|
local polyShape = self.shapes[self.shape]
|
|
local collidePoly = makePoly(polyShape, polyRadius)
|
|
|
|
local resolvedPoint = world.resolvePolyCollision(collidePoly, args.aimPosition, self.collideTolerance)
|
|
|
|
if resolvedPoint == nil then
|
|
drawDebugPoly(collidePoly, "red", args.aimPosition)
|
|
elseif resolvedPoint[1] == args.aimPosition[1] and resolvedPoint[2] == args.aimPosition[2] then
|
|
drawDebugPoly(collidePoly, "green", args.aimPosition)
|
|
else
|
|
world.debugLine(args.aimPosition, resolvedPoint, "yellow")
|
|
drawDebugPoly(collidePoly, "blue", resolvedPoint)
|
|
world.debugText(string.format("%.2f", world.magnitude(args.aimPosition, resolvedPoint)), args.aimPosition, "white")
|
|
end
|
|
end
|
|
|
|
function doLineCollision(args)
|
|
local lineRadius = self.radii[self.radius]
|
|
local lineMin = {args.aimPosition[1] - lineRadius, args.aimPosition[2] + lineRadius}
|
|
local lineMax = {args.aimPosition[1] + lineRadius, args.aimPosition[2] - lineRadius}
|
|
local colliding = world.lineTileCollision(lineMin, lineMax)
|
|
|
|
if colliding then
|
|
world.debugLine(lineMin, lineMax, "red")
|
|
else
|
|
world.debugLine(lineMin, lineMax, "green")
|
|
end
|
|
end
|
|
|
|
function makePoly(shape, radius)
|
|
if shape == "square" then
|
|
return {
|
|
{-radius, -radius},
|
|
{-radius, radius},
|
|
{radius, radius},
|
|
{radius, -radius}
|
|
}
|
|
elseif shape == "diamond" then
|
|
return {
|
|
{-radius, 0},
|
|
{0, radius},
|
|
{radius, 0},
|
|
{0, -radius}
|
|
}
|
|
elseif shape == "octagon" then
|
|
local smr = radius / 3
|
|
return {
|
|
{-radius, smr},
|
|
{-smr, radius},
|
|
{smr, radius},
|
|
{radius, smr},
|
|
{radius, -smr},
|
|
{smr, -radius},
|
|
{-smr, -radius},
|
|
{-radius, -smr}
|
|
}
|
|
end
|
|
|
|
sb.logInfo("Failed to make poly for shape %s and radius %s", shape, radius)
|
|
return {}
|
|
end
|
|
|
|
function drawDebugRect(rect, color, basePos)
|
|
if basePos then rect = translate(rect, basePos) end
|
|
world.debugLine({rect[1], rect[2]}, {rect[1], rect[4]}, color)
|
|
world.debugLine({rect[1], rect[2]}, {rect[3], rect[2]}, color)
|
|
world.debugLine({rect[3], rect[4]}, {rect[1], rect[4]}, color)
|
|
world.debugLine({rect[3], rect[4]}, {rect[3], rect[2]}, color)
|
|
end
|
|
|
|
function drawDebugPoly(poly, color, basePos)
|
|
local basePos = basePos or {0, 0}
|
|
if #poly >= 3 then
|
|
for i, point in ipairs(poly) do
|
|
world.debugLine(translate(point, basePos), translate(poly[(i % #poly) + 1], basePos), color)
|
|
end
|
|
end
|
|
end
|
|
|
|
function translate(pointOrRect, offset)
|
|
if #pointOrRect == 4 then
|
|
return {pointOrRect[1] + offset[1], pointOrRect[2] + offset[2], pointOrRect[3] + offset[1], pointOrRect[4] + offset[2]}
|
|
elseif #pointOrRect == 2 then
|
|
return {pointOrRect[1] + offset[1], pointOrRect[2] + offset[2]}
|
|
end
|
|
end
|
|
|
|
function printTable(t, indent)
|
|
if not indent then
|
|
indent = ""
|
|
sb.logInfo("Printing table...")
|
|
end
|
|
local tnames = {}
|
|
for k,v in pairs(t) do
|
|
tnames[#tnames + 1] = k
|
|
end
|
|
table.sort(tnames, function(a, b) return a < b end)
|
|
for _, key in ipairs(tnames) do
|
|
if type(t[key]) == "table" then
|
|
sb.logInfo(indent.."table "..key)
|
|
printTable(t[key], indent.." ")
|
|
elseif type(t[key]) == "function" then
|
|
sb.logInfo(indent.."function "..key)
|
|
else
|
|
sb.logInfo(indent..type(t[key]).." "..key.." = %s", t[key])
|
|
end
|
|
end
|
|
end
|