BlockSpawner.lua Part LUA Script File
Asset Details
Name = BlockSpawner.lua
Description = Part LUA Script File for 99540e2a-7727-422c-8725-d38cc8d34126 (BlockSpawner.lua)
Tags = script, scripted, lua
Author = 76561198014346778
RequiredAssets = 121
FileContents =
Description = Part LUA Script File for 99540e2a-7727-422c-8725-d38cc8d34126 (BlockSpawner.lua)
Tags = script, scripted, lua
Author = 76561198014346778
RequiredAssets = 121
FileContents =
dofile "Libs/Debugger.lua"
-- the following code prevents re-load of this file, except if in '-dev' mode.
if BlockSpawner and not sm.isDev then -- increases performance for non '-dev' users.
return
end
dofile("ShapeDatabase.lua")
mpPrint("loading BlockSpawner.lua")
-- BlockSpawner.lua --
BlockSpawner = class( nil )
BlockSpawner.maxChildCount = -1
BlockSpawner.maxParentCount = -1
BlockSpawner.connectionInput = sm.interactable.connectionType.logic + sm.interactable.connectionType.power
BlockSpawner.connectionOutput = sm.interactable.connectionType.logic
BlockSpawner.colorNormal = sm.color.new( 0x404040ff )
BlockSpawner.colorHighlight = sm.color.new( 0x606060ff )
BlockSpawner.poseWeightCount = 3
BlockSpawner.measureDistance = 20
--[[
-----------Logic signal-------------
Any logic = Spawn block/part
2nd grey = dynamic
3rd grey = forceSpawn
-----------Number signals-----------
2nd brown = offsetZ
2nd red = offsetY
2nd magenta = offsetX
white/Color Block = color
black = shapeID
4th brown = sizeZ
4th red = sizeY
4th magenta = sizeX
-----------Output-------------------
1 tick signal with a delay of 2 ticks if the block is spawned.
Can cause a false positive when there is lag present.
]]
function BlockSpawner.server_onRefresh( self )
self:server_onCreate()
end
function BlockSpawner.server_onCreate( self )
self.hasSpawned = false
self.lastSpawnedShape = nil
self.lastSpawnedShapeTick = nil
self.selfEnabled = false
--self.BlockSpawner = nil
end
function BlockSpawner.client_onCreate( self )
self:printDescription()
self:client_setSelfEnabled(false)
end
function BlockSpawner.printDescription()
-- Console doesn't have a monospace font ;(
local message = "Block Spawner Usage: \n"..
"---------------Logic signal------------------------ \n"..
"Any logic = Spawn block/part \n"..
"2nd grey = dynamic \n"..
"3rd grey = forceSpawn \n"..
"---------------Number signals------------------ \n"..
"2nd brown = offsetZ \n"..
"2nd red = offsetY \n"..
"2nd magenta = offsetX \n"..
"white/Color Block = color \n"..
"black/Sensor = shapeID \n"..
"4th brown = sizeZ \n"..
"4th red = sizeY \n"..
"4th magenta = sizeX \n"..
"---------------Output-------------------------------\n"..
"1 tick signal with a delay of 2 ticks if the block is spawned.\n"..
"Can cause a false positive when there is lag present.\n"..
"---------------------------------------------------------"
print(message)
end
function BlockSpawner.server_onFixedUpdate( self, timeStep )
self.interactable.active = false
local wantSpawn = false --If one of the parents is active
local offsetX = 0
local offsetY = 0
local offsetZ = 1
local color = nil
local rotation = nil --self.shape:getWorldRotation()
local uuid = nil
local numericId = 0
local raycastUuid = sm.uuid.getNil()
--local raycastColor = nil
local sizeX = 1
local sizeY = 1
local sizeZ = 1
local dynamic = true
local forceSpawn = false
local sensorShape = nil
local parents = self.interactable:getParents()
if #parents > 0 then
for k,v in pairs(parents) do
if v:getType() == "scripted" and tostring(v.shape.shapeUuid) ~= "6f2dd83e-bc0d-43f3-8ba5-d5209eb03d07" then -- Number stuff and not tick button
if tostring(v.shape.shapeUuid) == "921a2ace-b543-4ca3-8a9b-6f3dd3132fa9" then --colorblock
color = sm.color.new(v.power * 2^8 + 255)
elseif tostring(v.shape.shapeUuid) == "4081ca6f-6b80-4c39-9e79-e1f747039bec" then --smart sensor
if v.active then
sensorShape = v.shape
end
else
if tostring(v:getShape():getColor()) == "df7f00ff" then -- 2nd brown
offsetZ = v.power
elseif tostring(v:getShape():getColor()) == "d02525ff" then -- 2nd red
offsetY = v.power
elseif tostring(v:getShape():getColor()) == "cf11d2ff" then -- 2nd magenta
offsetX = v.power
elseif tostring(v:getShape():getColor()) == "eeeeeeff" then -- white
color = sm.color.new(v.power * 2^8 + 255)
elseif tostring(v:getShape():getColor()) == "472800ff" then -- 4th brown
sizeZ = v.power
elseif tostring(v:getShape():getColor()) == "560202ff" then -- 4th red
sizeY = v.power
elseif tostring(v:getShape():getColor()) == "520653ff" then -- 4th magenta
sizeX = v.power
elseif tostring(v:getShape():getColor()) == "222222ff" then -- black
numericId = round(v.power)
end
end
elseif v:getType() == "sensor" then
if v.active then
sensorShape = v.shape
end
else -- Logic
if tostring(v:getShape():getColor()) == "7f7f7fff" then -- 2nd grey
dynamic = v.active
elseif tostring(v:getShape():getColor()) == "4a4a4aff" then -- 3nd grey
forceSpawn = v.active
else
if not wantSpawn and v.active then
wantSpawn = true
end
end
end
end
end
local databaseEntry = shapeDatabase[tostring(numericId)]
if sensorShape == nil and numericId >= 0 then
if databaseEntry then
uuid = sm.uuid.new(databaseEntry.uuid)
else
uuid = sm.uuid.getNil()
end
else
numericId = nil
uuid = sm.uuid.getNil()
end
--print(sm.game.getCurrentTick(), self.shape.id, uuid)
--error()
--print(self.shape.id, self.lastSpawnedShape, self.lastSpawnedShape ~= nil and tostring(sm.exists(self.lastSpawnedShape)) or "")
self.interactable.active =
self.lastSpawnedShape ~= nil and
sm.exists(self.lastSpawnedShape) and
self.lastSpawnedShapeTick ~= nil and
sm.game.getCurrentTick() == self.lastSpawnedShapeTick + 1
--if self.interactable.active then
-- print(self.lastSpawnedShapeTick, sm.game.getCurrentTick(), self.lastSpawnedShapeTick, self.interactable.active, sm.game.getCurrentTick() - (self.lastSpawnedShapeTick ~= nil and self.lastSpawnedShapeTick or 0))
--end
self.lastSpawnedShape = nil
local selfEnabled = wantSpawn
if not self.hasSpawned and wantSpawn then
if numericId == nil then
--print(sm.game.getCurrentTick(), numericId)
--print("*pokes*", sensorShape, "go do raycast")
local hit,raycastResult = sm.physics.raycast(sensorShape.worldPosition, sensorShape.worldPosition + -sensorShape.up * self.measureDistance * -0.25)
if hit and raycastResult.type == "body" then
local rcShape = raycastResult:getShape()
--local rcJoint = raycastResult:getJoint() --Raycast does not hit joints. Bug?
if rcShape then
raycastUuid = rcShape.shapeUuid
color = rcShape.color
local lookedupId = shapeDatabaseLookup[tostring(raycastUuid)]
if lookedupId then
numericId = lookedupId
end
--print(shapeDatabaseLookup, lookedupId, numericId)
end
end
--if uuid == nil then
uuid = raycastUuid
--end
end
-- Try spawn
if uuid ~= sm.uuid.getNil() then
-- Calculate rotation
rotation = self.shape.worldRotation * sm.quat.new(0, 0.70710678118, 0.70710678118, 0) --sm.quat.lookRotation(-self.shape.up, self.shape.at)
-- Spawn block
local succes, spawnedShape = pcall(sm.shape.createBlock,
uuid,
sm.vec3.new(sizeX, sizeY, sizeZ),
self.shape:getWorldPosition() + rotation * sm.vec3.new(offsetX-0.5, offsetY-1, offsetZ-0.5) * 0.25,
rotation,
dynamic,
forceSpawn
)
-- If the UUID is not a block, it must be a part.
if not succes then
succes, spawnedShape = pcall(sm.shape.createPart,
uuid,
self.shape:getWorldPosition() + rotation * sm.vec3.new(offsetX-0, offsetY-0.5, offsetZ-0.5) * 0.25,
rotation,
dynamic,
forceSpawn
)
end
if succes and color then -- Set the color of the spawned shape
spawnedShape.color = color
--print(self.shape:getBoundingBox(), self.shape:getWorldPosition(), spawnedShape:getWorldPosition(), self.shape:getWorldPosition()-spawnedShape:getWorldPosition())
end
self.lastSpawnedShape = succes and spawnedShape or nil
self.lastSpawnedShapeTick = succes and sm.game.getCurrentTick() or nil
self.hasSpawned = true
else
self.hasSpawned = true
end
--selfEnabled = true
if numericId then
self.network:sendToClients("client_setDisplay", numericId)
end
elseif self.hasSpawned and not wantSpawn then
self.hasSpawned = false
end
if selfEnabled ~= self.selfEnabled then
self.network:sendToClients("client_setSelfEnabled", selfEnabled)
self.selfEnabled = selfEnabled
end
end
function BlockSpawner.client_setDisplay( self, value )
self.interactable:setUvFrameIndex(value)
end
function BlockSpawner.client_setSelfEnabled( self, value )
--self.interactable:setPoseWeight(0, value and 1 or 0)
self:client_setLightRedEnabled(not value)
self:client_setLightGreenEnabled(value)
end
function BlockSpawner.client_setLightRedEnabled( self, value )
self.interactable:setPoseWeight(1, value and 1 or 0)
end
function BlockSpawner.client_setLightGreenEnabled( self, value )
self.interactable:setPoseWeight(2, value and 1 or 0)
end
function round(x)
if x%2 ~= 0.5 then
return math.floor(x+0.5)
end
return x-0.5
end