local dust = {} local redstone = require("redstone") local npcManager = require("npcManager") local insert, iclone = table.insert, table.iclone dust.name = "dust" dust.id = NPC_ID dust.test = function() return "isDust", function(x) return (x == dust.id or x == dust.name) end end dust.config = npcManager.setNpcSettings({ id = dust.id, width = 32, height = 32, gfxwidth = 32, gfxheight = 32, gfxoffsetx = 0, gfxoffsety = 0, frames = 1, framespeed = 8, framestyle = 0, invisible = false, noblockcollision = true, notcointransformable = true, nogravity = true, jumphurt = true, nohurt = true, noyoshi = true, basicdust = false, -- A less laggy, but less accurate dust AI debug = false, -- Debugs the power level of the NPC automap = true -- Automaps index 0 automatically }) local dustMap = {} dustMap["true true true true"] = 1 dustMap["true false true false"] = 2 dustMap["false true false true"] = 3 dustMap["false false true true"] = 4 dustMap["false true true false"] = 5 dustMap["true true false false"] = 6 dustMap["true false false true"] = 7 dustMap["true false true true"] = 8 dustMap["false true true true"] = 9 dustMap["true true true false"] = 10 dustMap["true true false true"] = 11 dustMap["true false false false"] = 12 dustMap["false true false false"] = 13 dustMap["false false true false"] = 14 dustMap["false false false true"] = 15 dustMap["false false false false"] = 16 local function foundDust(n, coll) for k, v in NPC.iterateIntersecting(coll.x, coll.y, coll.x + coll.width, coll.y + coll.height) do if redstone.comList[v.id] and v ~= n and n.layerName == v.layerName and (v.id ~= dust.id or v.data.colorType == n.data.colorType) then return true end end return false end local function setFrameX(n) redstone.updateRedHitBox(n) local redhitbox = n.data.redhitbox local fLeft = foundDust(n, redhitbox[1]) local fUp = foundDust(n, redhitbox[2]) local fRight = foundDust(n, redhitbox[3]) local fDown = foundDust(n, redhitbox[4]) n.data.frameX = dustMap[tostring(fLeft).." "..tostring(fUp).." "..tostring(fRight).." "..tostring(fDown)] or 0 end local dustQueque = {} local dustRemain = {} -- Look guys, I tried my best here. local function instantpower(n) local power = n.data.power local list = NPC.get(redstone.comID, n.section) --Colliders.getColliding{a = data.redarea, b = redstone.comID, btype = Colliders.NPC, filter = redstone.nofilter} dustRemain = {n} dustQueque = {} while dustRemain[1] do for _, dust in ipairs(dustRemain) do local data = dust.data for dir, coll in ipairs(data.redhitbox) do for k = #list, 1, -1 do local v = list[k] if Colliders.collide(v, coll) then if v.id == dust.id then if v ~= dust and data.power > v.data.power + 1 and data.colorType == v.data.colorType then redstone.setEnergy(v, dust.data.power - 1) redstone.updateRedArea(v) redstone.updateRedHitBox(v) insert(dustQueque, v) end else redstone.energyFilter(v, dust, dust.data.power, dir - 1, coll) end end end end end dustRemain = iclone(dustQueque) dustQueque = {} end end function dust.prime(n) local data = n.data data.animFrame = data.animFrame or 0 data.animTimer = data.animTimer or 0 data.frameX = (data._settings.mapX or 1) data.frameY = data.frameY or 0 data.colorType = data._settings.color or 0 data.pistIgnore = data.pistIgnore or true data.isTransparent = data.isTransparent or true data.redarea = data.redarea or redstone.basicRedArea(n) data.redhitbox = data.redhitbox or redstone.basicRedHitBox(n) n.priority = -46 end local function onRedPowerBasic(n, c, p, d, hitbox) if c.id == dust.id then if c.data.colorType == n.data.colorType then redstone.setEnergy(n, p - 1) end else redstone.setEnergy(n, p) end end local function onRedTickBasic(n) local data = n.data data.observ = false if dust.config.automap and data.frameX == 0 then setFrameX(n) end if data.power > 0 then redstone.updateRedArea(n) redstone.updateRedHitBox(n) redstone.passEnergy{source = n, power = data.power, hitbox = data.redhitbox, area = data.redarea} end if data.power == 0 then data.frameY = 0 elseif data.power < 8 then data.frameY = 1 else data.frameY = 2 end data.frameY = data.frameY + 3*data.colorType data.observ = data.powerPrev ~= data.power redstone.resetPower(n) end local function onRedPowerComplex(n, c, p, d, hitbox) if not redstone.is.dust(c.id) then redstone.setEnergy(n, p) redstone.updateRedArea(n) redstone.updateRedHitBox(n) instantpower(n) end end local function onRedTickComplex(n, v) local data = n.data data.observ = false if dust.config.automap and data.frameX == 0 then setFrameX(n) end end local function onRedTickEndComplex(n) local data = n.data if data.power == 0 then data.frameY = 0 elseif data.power >= 8 then data.frameY = 2 else data.frameY = 1 end data.frameY = data.frameY + 3*data.colorType if dust.config.debug and not n.isHidden then redstone.printNPC(n.data.power, n, 12, 12) end data.observ = data.powerPrev ~= data.power redstone.resetPower(n) end if dust.config.basicdust then dust.onRedPower = onRedPowerBasic dust.onRedTick = onRedTickBasic else dust.onRedPower = onRedPowerComplex dust.onRedTick = onRedTickComplex dust.onRedTickEnd = onRedTickEndComplex end dust.onRedDraw = redstone.drawNPC redstone.register(dust) return dust