You can write your topic however you want, but you need to answer these questions:
- What do you want to achieve? I wanna use A fire module
- What is the issue? So it used a table as matinfo = materials[part.Material] and when I print mat info it print {…} So its a table inside is some property ex [BurnTemp] = 100 but the error at
local burning = info.Temperature >= matInfo.IgnitionTemp and info.PercentBurned < 100
And at the end it print nil,So why is that?
- What solutions have you tried so far? Ive tryed debugging and looked here but the solution to my problem is not to be found
All the script from someone 400 line
--Fire simulation script
--Dominik Wandernoth 11/2015
--Global 'constants'
local doDebug = script.Configuration.DoDebug.Value
local ambientTemp = script.Configuration.AmbientTemperature.Value
local convectionMultiplier = 1/script.Configuration.ConvectionSpeed.Value
local conductionMultiplierTouching = 1/script.Configuration.ConductionSpeedTouch.Value
local conductionMuldiplierConnected = 1/script.Configuration.ConductionSpeedWelded.Value
local materialStrength = script.Configuration.MaterialStrength.Value
local damageCharacters = script.Configuration.CharactersTakeDamage.Value
local charDamageThreshold = script.Configuration.CharacterDamageThreshold.Value
local charDamageMultiplier = script.Configuration.CharacterDamageMultiplier.Value
local recalcChance = script.Configuration.RecalcChance.Value
local breakAtPercentBurned = script.Configuration.BreakAtPercentBurned.Value
local deltaTVoxelTransferThreshhold = script.Configuration.DeltaTVoxelTransferThreshhold.Value
local voxelCenterTemperatureWeight = script.Configuration.VoxelCenterTemperatureWeight.Value
local voxelUpTemperatureWeight = script.Configuration.VoxelUpTemperatureWeight.Value
local voxelDownTemperatureWeight = script.Configuration.VoxelDownTemperatureWeight.Value
local voxelSideTemperatureWeight = script.Configuration.VoxelSideTemperatureWeight.Value
local deltaTPartTransferThreshhold = script.Configuration.DeltaTPartTransferThreshhold.Value
local tempBeginGlow = script.Configuration.TempBeginGlow.Value
local tempToMaxGlow = script.Configuration.TempToMaxGlow.Value
--Allow changing them at runtime
script.Configuration.DoDebug.Changed:connect(function() doDebug = script.Configuration.DoDebug.Value end)
script.Configuration.AmbientTemperature.Changed:connect(function() ambientTemp = script.Configuration.AmbientTemperature.Value end)
script.Configuration.ConvectionSpeed.Changed:connect(function() convectionMultiplier = 1/script.Configuration.ConvectionSpeed.Value end)
script.Configuration.ConductionSpeedTouch.Changed:connect(function() conductionMultiplierTouching = 1/script.Configuration.ConductionSpeedTouch.Value end)
script.Configuration.ConductionSpeedWelded.Changed:connect(function() conductionMuldiplierConnected = 1/script.Configuration.ConductionSpeedWelded.Value end)
script.Configuration.MaterialStrength.Changed:connect(function() materialStrength = script.Configuration.MaterialStrength.Value end)
script.Configuration.CharactersTakeDamage.Changed:connect(function() damageCharacters = script.Configuration.CharactersTakeDamage.Value end)
script.Configuration.CharacterDamageThreshold.Changed:connect(function() charDamageThreshold = script.Configuration.CharacterDamageThreshold.Value end)
script.Configuration.CharacterDamageMultiplier.Changed:connect(function() charDamageMultiplier = script.Configuration.CharacterDamageMultiplier.Value end)
script.Configuration.RecalcChance.Changed:connect(function() recalcChance = script.Configuration.RecalcChance.Value end)
script.Configuration.BreakAtPercentBurned.Changed:connect(function() breakAtPercentBurned = script.Configuration.BreakAtPercentBurned.Value end)
script.Configuration.DeltaTVoxelTransferThreshhold.Changed:connect(function() deltaTVoxelTransferThreshhold = script.Configuration.DeltaTVoxelTransferThreshhold.Value end)
script.Configuration.VoxelCenterTemperatureWeight.Changed:connect(function() voxelCenterTemperatureWeight = script.Configuration.VoxelCenterTemperatureWeight.Value end)
script.Configuration.VoxelUpTemperatureWeight.Changed:connect(function() voxelUpTemperatureWeight = script.Configuration.VoxelUpTemperatureWeight.Value end)
script.Configuration.VoxelDownTemperatureWeight.Changed:connect(function() voxelDownTemperatureWeight = script.Configuration.VoxelDownTemperatureWeight.Value end)
script.Configuration.VoxelSideTemperatureWeight.Changed:connect(function() voxelSideTemperatureWeight = script.Configuration.VoxelSideTemperatureWeight.Value end)
script.Configuration.DeltaTPartTransferThreshhold.Changed:connect(function() deltaTPartTransferThreshhold = script.Configuration.DeltaTPartTransferThreshhold.Value end)
script.Configuration.TempBeginGlow.Changed:connect(function() tempBeginGlow = script.Configuration.TempBeginGlow.Value end)
script.Configuration.TempToMaxGlow.Changed:connect(function() tempToMaxGlow = script.Configuration.TempToMaxGlow.Value end)
--Perf upgrade (This one is for free so why not)
local max = math.max
local min = math.min
local abs = math.abs
local random = math.random
local pow = math.pow
local vec3 = Vector3.new
local newcf = CFrame.new
--Material properties
--Helper function to load configurations
function loadConfig(folder)
local out = {}
out.BurnTemp = folder.BurnTemp.Value
out.IgnitionTemp = (folder.IsFlammable.Value and folder.IgnitionTemp.Value or math.huge)
out.SpecificHeat = folder.SpecificHeat.Value
return out
end
--Although we're not going for absolute realism, we do want the materials to compare
--to eachother in a realistic way. Therefore, the following values will be researched.
--[[Sources:
http://www.tcforensic.com.au/docs/article10.html
http://www.engineeringtoolbox.com/specific-heat-solids-d_154.html
http://www.northseaplastics.com/documents/abs_safety_datasheet.pdf
--]]
local materials = {
[Enum.Material.Plastic] = loadConfig(script.Configuration.Materials.Plastic);
[Enum.Material.SmoothPlastic] = loadConfig(script.Configuration.Materials.SmoothPlastic);
[Enum.Material.Wood] = loadConfig(script.Configuration.Materials.Wood);
[Enum.Material.WoodPlanks] = loadConfig(script.Configuration.Materials.WoodPlanks);
[Enum.Material.Metal] = loadConfig(script.Configuration.Materials.Metal);
[Enum.Material.DiamondPlate] = loadConfig(script.Configuration.Materials.DiamondPlate);
[Enum.Material.CorrodedMetal] = loadConfig(script.Configuration.Materials.CorrodedMetal);
[Enum.Material.Foil] = loadConfig(script.Configuration.Materials.Foil);
[Enum.Material.Sand] = loadConfig(script.Configuration.Materials.Sand);
[Enum.Material.Neon] = loadConfig(script.Configuration.Materials.Neon);
[Enum.Material.Ice] = loadConfig(script.Configuration.Materials.Ice);
[Enum.Material.Fabric] = loadConfig(script.Configuration.Materials.Fabric);
[Enum.Material.Grass] = loadConfig(script.Configuration.Materials.Grass);
[Enum.Material.Granite] = loadConfig(script.Configuration.Materials.Granite);
[Enum.Material.Slate] = loadConfig(script.Configuration.Materials.Slate);
[Enum.Material.Pebble] = loadConfig(script.Configuration.Materials.Pebble);
[Enum.Material.Concrete] = loadConfig(script.Configuration.Materials.Concrete);
[Enum.Material.Cobblestone] = loadConfig(script.Configuration.Materials.Cobblestone);
[Enum.Material.Marble] = loadConfig(script.Configuration.Materials.Marble);
[Enum.Material.Brick] = loadConfig(script.Configuration.Materials.Brick);
}
--Performance ugly fix
local lastthrottle = tick()
function throttle(tlimit,name)
if (tlimit < tick()-lastthrottle) then
if (doDebug) then print(name .. " throttled at " .. math.floor((tick()-lastthrottle)*100e3)/100 .. " ms") end
wait()
lastthrottle = tick()
end
end
--Temperature voxel system
local voxels = {}
local recalcVoxels = {}
function defaultVoxel()
return {
Temperature = ambientTemp;
DoRecalc = false;
}
end
local function getVoxel(x,y,z)
if (voxels[x] == nil or voxels[x][y] == nil or voxels[x][y][z] == nil) then return defaultVoxel() end
return voxels[x][y][z]
end
local function setVoxel(x,y,z,voxel)
if (voxels[x] == nil) then voxels[x] = {} end
if (voxels[x][y] == nil) then voxels[x][y] = {} end
voxels[x][y][z] = voxel
end
local function registerVoxelUpdate(x,y,z,temp,weight)
local index = (x .. "," .. y .. "," .. z)
local v = getVoxel(x,y,z)
v.DoRecalc = true
setVoxel(x,y,z,v)
if (recalcVoxels[index]) then
table.insert(recalcVoxels[index][2],{temp,weight})
else
recalcVoxels[index] = {Vector3.new(x,y,z),{{temp,weight}}}
end
end
function voxelTick()
local requiresRerun = false
local ticks = 0
local t = tick()
for key,value in pairs(recalcVoxels) do
ticks = ticks + 1
local temp,wsum = 0,0
for _,v in pairs(value[2]) do
temp,wsum = temp+v[1]*v[2],wsum+v[2]
end
local pos = value[1]
local voxel = getVoxel(pos.x,pos.y,pos.z)
temp = temp + voxel.Temperature * voxelCenterTemperatureWeight
wsum = wsum + voxelCenterTemperatureWeight
local voxUp = getVoxel(pos.x,pos.y+1,pos.z)
local voxDn = getVoxel(pos.x,pos.y-1,pos.z)
local voxLt = getVoxel(pos.x-1,pos.y,pos.z)
local voxRt = getVoxel(pos.x+1,pos.y,pos.z)
local voxFt = getVoxel(pos.x,pos.y,pos.z-1)
local voxBk = getVoxel(pos.x,pos.y,pos.z+1)
temp = temp
+ voxUp.Temperature * voxelUpTemperatureWeight
+ voxDn.Temperature * voxelDownTemperatureWeight
+ voxLt.Temperature * voxelSideTemperatureWeight
+ voxRt.Temperature * voxelSideTemperatureWeight
+ voxFt.Temperature * voxelSideTemperatureWeight
+ voxBk.Temperature * voxelSideTemperatureWeight
wsum = wsum + 4*voxelSideTemperatureWeight + voxelDownTemperatureWeight + voxelUpTemperatureWeight
voxel.Temperature = temp/wsum
voxel.DoRerun = voxel.Temperature > ambientTemp+10
if (abs(voxUp.Temperature - voxel.Temperature) > deltaTVoxelTransferThreshhold or math.random(0,100) < recalcChance) then registerVoxelUpdate(pos.x,pos.y+1,pos.z,0,0) end
if (abs(voxDn.Temperature - voxel.Temperature) > deltaTVoxelTransferThreshhold or math.random(0,100) < recalcChance) then registerVoxelUpdate(pos.x,pos.y-1,pos.z,0,0) end
if (abs(voxLt.Temperature - voxel.Temperature) > deltaTVoxelTransferThreshhold or math.random(0,100) < recalcChance) then registerVoxelUpdate(pos.x-1,pos.y,pos.z,0,0) end
if (abs(voxRt.Temperature - voxel.Temperature) > deltaTVoxelTransferThreshhold or math.random(0,100) < recalcChance) then registerVoxelUpdate(pos.x+1,pos.y,pos.z,0,0) end
if (abs(voxFt.Temperature - voxel.Temperature) > deltaTVoxelTransferThreshhold or math.random(0,100) < recalcChance) then registerVoxelUpdate(pos.x,pos.y,pos.z-1,0,0) end
if (abs(voxBk.Temperature - voxel.Temperature) > deltaTVoxelTransferThreshhold or math.random(0,100) < recalcChance) then registerVoxelUpdate(pos.x,pos.y,pos.z+1,0,0) end
if (not voxel.DoRerun) then
recalcVoxels[key] = nil
else
requiresRerun = true
recalcVoxels[key][2] = {}
end
throttle(0.05,"Voxel updates")
end
return requiresRerun,ticks
end
--Buncha fancy math to check collisions
local function checkVoxelVsOBB(P,CF,S)
P=P*4
S=S/2
local sx,sy,sz=S.X,S.Y,S.Z
local x,y,z,a,b,c,d,e,f,g,h,i = CF:components()
local x1,y1,z1=x+( sx*a+sy*b+sz*c),y+( sx*d+sy*e+sz*f),z+( sx*g+sy*h+sz*i)
local x2,y2,z2=x+( sx*a+sy*b-sz*c),y+( sx*d+sy*e-sz*f),z+( sx*g+sy*h-sz*i)
local x3,y3,z3=x+( sx*a-sy*b+sz*c),y+( sx*d-sy*e+sz*f),z+( sx*g-sy*h+sz*i)
local x4,y4,z4=x+( sx*a-sy*b-sz*c),y+( sx*d-sy*e-sz*f),z+( sx*g-sy*h-sz*i)
local x5,y5,z5=x+(-sx*a+sy*b+sz*c),y+(-sx*d+sy*e+sz*f),z+(-sx*g+sy*h+sz*i)
local x6,y6,z6=x+(-sx*a+sy*b-sz*c),y+(-sx*d+sy*e-sz*f),z+(-sx*g+sy*h-sz*i)
local x7,y7,z7=x+(-sx*a-sy*b+sz*c),y+(-sx*d-sy*e+sz*f),z+(-sx*g-sy*h+sz*i)
local x8,y8,z8=x+(-sx*a-sy*b-sz*c),y+(-sx*d-sy*e-sz*f),z+(-sx*g-sy*h-sz*i)
local ux,uy,uz=max(x1,x2,x3,x4,x5,x6,x7,x8),max(y1,y2,y3,y4,y5,y6,y7,y8),max(z1,z2,z3,z4,z5,z6,z7,z8)
local lx,ly,lz=min(x1,x2,x3,x4,x5,x6,x7,x8),min(y1,y2,y3,y4,y5,y6,y7,y8),min(z1,z2,z3,z4,z5,z6,z7,z8)
local llx,lly,llz,ulx,uly,ulz=P.X-2,P.Y-2,P.Z-2,P.X+2,P.Y+2,P.Z+2
if(lx>=llx and lx<=ulx)or(ux>=llx and ux<=ulx)or(ux>=ulx and lx<=llx)then
if(ly>=lly and ly<=uly)or(uy>=lly and uy<=uly)or(uy>=uly and ly<=lly)then
if(lz>=llz and lz<=ulz)or(uz>=llz and uz<=ulz)or(uz>=ulz and lz<=llz)then
local x,y,z,a,b,c,d,e,f,g,h,i = CF:toObjectSpace(newcf(P)):components()
local x1,y1,z1=x+( 2*a+2*b+2*c),y+( 2*d+2*e+2*f),z+( 2*g+2*h+2*i)
local x2,y2,z2=x+( 2*a+2*b-2*c),y+( 2*d+2*e-2*f),z+( 2*g+2*h-2*i)
local x3,y3,z3=x+( 2*a-2*b+2*c),y+( 2*d-2*e+2*f),z+( 2*g-2*h+2*i)
local x4,y4,z4=x+( 2*a-2*b-2*c),y+( 2*d-2*e-2*f),z+( 2*g-2*h-2*i)
local x5,y5,z5=x+(-2*a+2*b+2*c),y+(-2*d+2*e+2*f),z+(-2*g+2*h+2*i)
local x6,y6,z6=x+(-2*a+2*b-2*c),y+(-2*d+2*e-2*f),z+(-2*g+2*h-2*i)
local x7,y7,z7=x+(-2*a-2*b+2*c),y+(-2*d-2*e+2*f),z+(-2*g-2*h+2*i)
local x8,y8,z8=x+(-2*a-2*b-2*c),y+(-2*d-2*e-2*f),z+(-2*g-2*h-2*i)
local ux,uy,uz=max(x1,x2,x3,x4,x5,x6,x7,x8),max(y1,y2,y3,y4,y5,y6,y7,y8),max(z1,z2,z3,z4,z5,z6,z7,z8)
local lx,ly,lz=min(x1,x2,x3,x4,x5,x6,x7,x8),min(y1,y2,y3,y4,y5,y6,y7,y8),min(z1,z2,z3,z4,z5,z6,z7,z8)
local llx,lly,llz,ulx,uly,ulz=-S.X,-S.Y,-S.Z,S.X,S.Y,S.Z
if(lx>=llx and lx<=ulx)or(ux>=llx and ux<=ulx)or(ux>=ulx and lx<=llx)then
if(ly>=lly and ly<=uly)or(uy>=lly and uy<=uly)or(uy>=uly and ly<=lly)then
if(lz>=llz and lz<=ulz)or(uz>=llz and uz<=ulz)or(uz>=ulz and lz<=llz)then
local sx,sy,sz = min(ux,ulx)-max(lx,llx),min(uy,uly)-max(ly,lly),min(uz,ulz)-max(lz,llz)
return true,sx*sy*sz
end end end
return false,0
end end end
return false,0
end
local function checkOBBVsOBB(CF1,S1,CF2,S2)
S1 = S1 / 2
S2 = S2 / 2
local sx,sy,sz=S2.X,S2.Y,S2.Z
local x,y,z,a,b,c,d,e,f,g,h,i = CF1:toObjectSpace(CF2):components()
local x1,y1,z1=x+( sx*a+sy*b+sz*c),y+( sx*d+sy*e+sz*f),z+( sx*g+sy*h+sz*i)
local x2,y2,z2=x+( sx*a+sy*b-sz*c),y+( sx*d+sy*e-sz*f),z+( sx*g+sy*h-sz*i)
local x3,y3,z3=x+( sx*a-sy*b+sz*c),y+( sx*d-sy*e+sz*f),z+( sx*g-sy*h+sz*i)
local x4,y4,z4=x+( sx*a-sy*b-sz*c),y+( sx*d-sy*e-sz*f),z+( sx*g-sy*h-sz*i)
local x5,y5,z5=x+(-sx*a+sy*b+sz*c),y+(-sx*d+sy*e+sz*f),z+(-sx*g+sy*h+sz*i)
local x6,y6,z6=x+(-sx*a+sy*b-sz*c),y+(-sx*d+sy*e-sz*f),z+(-sx*g+sy*h-sz*i)
local x7,y7,z7=x+(-sx*a-sy*b+sz*c),y+(-sx*d-sy*e+sz*f),z+(-sx*g-sy*h+sz*i)
local x8,y8,z8=x+(-sx*a-sy*b-sz*c),y+(-sx*d-sy*e-sz*f),z+(-sx*g-sy*h-sz*i)
local ux,uy,uz=max(x1,x2,x3,x4,x5,x6,x7,x8),max(y1,y2,y3,y4,y5,y6,y7,y8),max(z1,z2,z3,z4,z5,z6,z7,z8)
local lx,ly,lz=min(x1,x2,x3,x4,x5,x6,x7,x8),min(y1,y2,y3,y4,y5,y6,y7,y8),min(z1,z2,z3,z4,z5,z6,z7,z8)
local llx,lly,llz,ulx,uly,ulz=-S1.X,-S1.Y,-S1.Z,S1.X,S1.Y,S1.Z
if(lx>=llx and lx<=ulx)or(ux>=llx and ux<=ulx)or(ux>=ulx and lx<=llx)then
if(ly>=lly and ly<=uly)or(uy>=lly and uy<=uly)or(uy>=uly and ly<=lly)then
if(lz>=llz and lz<=ulz)or(uz>=llz and uz<=ulz)or(uz>=ulz and lz<=llz)then
local x,y,z,a,b,c,d,e,f,g,h,i = CF2:toObjectSpace(CF1):components()
local x1,y1,z1=x+( sx*a+sy*b+sz*c),y+( sx*d+sy*e+sz*f),z+( sx*g+sy*h+sz*i)
local x2,y2,z2=x+( sx*a+sy*b-sz*c),y+( sx*d+sy*e-sz*f),z+( sx*g+sy*h-sz*i)
local x3,y3,z3=x+( sx*a-sy*b+sz*c),y+( sx*d-sy*e+sz*f),z+( sx*g-sy*h+sz*i)
local x4,y4,z4=x+( sx*a-sy*b-sz*c),y+( sx*d-sy*e-sz*f),z+( sx*g-sy*h-sz*i)
local x5,y5,z5=x+(-sx*a+sy*b+sz*c),y+(-sx*d+sy*e+sz*f),z+(-sx*g+sy*h+sz*i)
local x6,y6,z6=x+(-sx*a+sy*b-sz*c),y+(-sx*d+sy*e-sz*f),z+(-sx*g+sy*h-sz*i)
local x7,y7,z7=x+(-sx*a-sy*b+sz*c),y+(-sx*d-sy*e+sz*f),z+(-sx*g-sy*h+sz*i)
local x8,y8,z8=x+(-sx*a-sy*b-sz*c),y+(-sx*d-sy*e-sz*f),z+(-sx*g-sy*h-sz*i)
local ux,uy,uz=max(x1,x2,x3,x4,x5,x6,x7,x8),max(y1,y2,y3,y4,y5,y6,y7,y8),max(z1,z2,z3,z4,z5,z6,z7,z8)
local lx,ly,lz=min(x1,x2,x3,x4,x5,x6,x7,x8),min(y1,y2,y3,y4,y5,y6,y7,y8),min(z1,z2,z3,z4,z5,z6,z7,z8)
local llx,lly,llz,ulx,uly,ulz=-S2.X,-S2.Y,-S2.Z,S2.X,S2.Y,S2.Z
if(lx>=llx and lx<=ulx)or(ux>=llx and ux<=ulx)or(ux>=ulx and lx<=llx)then
if(ly>=lly and ly<=uly)or(uy>=lly and uy<=uly)or(uy>=uly and ly<=lly)then
if(lz>=llz and lz<=ulz)or(uz>=llz and uz<=ulz)or(uz>=ulz and lz<=llz)then
local sx,sy,sz = min(ux,ulx)-max(lx,llx),min(uy,uly)-max(ly,lly),min(uz,ulz)-max(lz,llz)
return true,sx*sy*sz
end end end
return false,0
end end end
return false,0
end
local function getVoxelIntersects(part)
local s = part.Size
local dim = vec3(max(s.x,4),max(s.y,4),max(s.z,4))/2
local intersections = {}
local sum = 0
for x = -dim.x,dim.x,4 do
for y = -dim.y,dim.y,4 do
for z = -dim.z,dim.z,4 do
local p = part.CFrame * newcf(x,y,z)
p = vec3(math.floor(p.x/4 + 0.5),math.floor(p.y/4 + 0.5),math.floor(p.z/4 + 0.5))
local c,s = checkVoxelVsOBB(p,part.CFrame,part.Size)
if (c) then
intersections[p] = s
sum = sum + s
end
end
end
end
for k,v in pairs(intersections) do intersections[k] = v/sum end
return intersections
end
--Template voxel
--Voxel = {
-- Temperature = 20;
-- DoRecalc = false;
--}
--Is the part in water?
local function isSubmerged(part)
local s = math.max(2,part.Size.magnitude/2)
local region = Region3.new(part.Position-Vector3.new(1,1,1)*s,part.Position+Vector3.new(1,1,1)*s)
region = region:ExpandToGrid(4)
local material, occupancy = game.Workspace.Terrain:ReadVoxels(region, 4)
local size = material.Size
for x = 1, size.X do
for y = 1, size.Y do
for z = 1, size.Z do
if (material[x][y][z] == Enum.Material.Water and occupancy[x][y][z] > 0.5) then
return true
end
end
end
end
return false
end
--Temperature to color
--http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
--These "magic numbers" come from research I've done at the above website; In fact, this is their code converted into Lua.
function tempToColor3(tmpKelvin)
--Temperature must fall between 1000 and 40000 degrees
if (tmpKelvin < 1000) then tmpKelvin = 1000 end
if (tmpKelvin > 40000) then tmpKelvin = 40000 end
--All calculations require tmpKelvin / 100, so only do the conversion once
tmpKelvin = tmpKelvin / 100
--Calculate each color in turn
local r,g,b = 0,0,0
--First: red
if (tmpKelvin <= 66) then
r = 255
else
--Note: the R-squared value for this approximation is .988
local tmpCalc = tmpKelvin - 60
tmpCalc = 329.698727446 * (tmpCalc ^ -0.1332047592)
r = tmpCalc
if (r < 0) then r = 0 end
if (r > 255) then r = 255 end
end
--Second: green
if (tmpKelvin <= 66) then
--Note: the R-squared value for this approximation is .996
local tmpCalc = tmpKelvin
tmpCalc = 99.4708025861 * math.log(tmpCalc) - 161.1195681661
g = tmpCalc
if (g < 0) then g = 0 end
if (g > 255) then g = 255 end
else
--Note: the R-squared value for this approximation is .987
local tmpCalc = tmpKelvin - 60
tmpCalc = 288.1221695283 * (tmpCalc ^ -0.0755148492)
g = tmpCalc
if (g < 0) then g = 0 end
if (g > 255) then g = 255 end
end
--Third: blue
if (tmpKelvin >= 66) then
b = 255
elseif (tmpKelvin <= 19) then
b = 0
else
--Note: the R-squared value for this approximation is .998
local tmpCalc = tmpKelvin - 10
tmpCalc = 138.5177312231 * math.log(tmpCalc) - 305.0447927307
b = tmpCalc
if (b < 0) then b = 0 end
if (b > 255) then b = 255 end
end
return Color3.new(r/255,g/255,b/255)
end
--Register all parts
parts = {}
function registerPart(dir)
local glowPart = dir:clone()
glowPart.Material = "Neon"
glowPart.Size = dir.Size + vec3(0.1,0.1,0.1) --Glow part should be slightly bigger to avoid Z-Fighting
glowPart.Transparency = 1
glowPart.Name = "HeatGlow"
glowPart.CanCollide = false
glowPart.Parent = dir
glowPart:ClearAllChildren()
local glowLight = Instance.new("PointLight")
glowLight.Brightness = 0
glowLight.Color = Color3.new(1,0,0)
glowLight.Parent = dir
local w = Instance.new("Weld")
w.Part0 = dir
w.Part1 = glowPart
w.Parent = dir
Instance.new("BlockMesh",glowPart)
local fireParticles = script.FireParticles:clone()
fireParticles.Parent = dir
parts[dir] = {
Temperature = ambientTemp;
Phase = "NotInit";
DoRecalc = true;
Fire = fireParticles;
Light = glowLight;
PercentBurned = 0;
Glow = glowPart;
}
end
function registerParts(dir)
if (dir:IsA("BasePart") and not dir:IsA("Terrain") and parts[dir] == nil and dir.Size.Magnitude < 100) then
registerPart(dir)
end
for _,part in pairs(dir:children()) do
if (part.Name ~= "HeatGlow") then registerParts(part) end
end
throttle(0.05,"Part registration")
end
function doCalc()
local requiresRerun = false
local calcs = 0
for part,info in pairs(parts) do
if (info.DoRecalc or random(0,100) < recalcChance) then --Randomly choose to recalculate anyways, based on the config option
calcs = calcs + 1
local markForDelete = false
--First, get the material properties table
local matInfo = materials[part.Material]
--Average ambient temperature & Setting voxel temp
local intersects = getVoxelIntersects(part)
local temp = 0
for k,v in pairs(intersects) do
local voxel = getVoxel(k.x,k.y,k.z)
temp = temp + v*voxel.Temperature
end
--Let's deal with burning/not burning first
--if matInfo == nil then return end
print(matInfo)
local burning = info.Temperature >= matInfo.IgnitionTemp and info.PercentBurned < 100
--Being submerged might change this
if (isSubmerged(part)) then
local s = part.Size
local surfaceArea = 2*(s.y*s.z+s.x*s.z+s.x*s.y)
local delta = (temp - info.Temperature) / max((part:GetMass() * matInfo.SpecificHeat * convectionMultiplier * 3)/surfaceArea,1)
info.Temperature = info.Temperature + delta
end
if (burning) then
local flameTemp = matInfo.BurnTemp
local s = part.Size
local surfaceArea = 2*(s.y*s.z+s.x*s.z+s.x*s.y)
local delta = (flameTemp - info.Temperature) / max((part:GetMass() * matInfo.SpecificHeat * convectionMultiplier)/surfaceArea,1)
info.Temperature = info.Temperature + delta
local colorTemp = max(flameTemp,info.Temperature)*2
local color1,color2 = tempToColor3(colorTemp),tempToColor3(colorTemp/2)
info.Fire.Enabled = true
--info.Fire.Size = part.Size.magnitude*2
info.Fire.Color = ColorSequence.new(color1,color2)
info.Fire.Acceleration = Vector3.new(0,info.Temperature/100,0)
local volume = s.x*s.y*s.z
info.PercentBurned = info.PercentBurned + (info.Temperature / matInfo.IgnitionTemp) * (surfaceArea/volume) * (1/materialStrength)
if (info.PercentBurned > breakAtPercentBurned and not info.Burnt) then
part.BrickColor = BrickColor.new("Really black")
part:breakJoints()
--Unions like to force color, so we'll tell it to turn black anyways
if (part:IsA("UnionOperation")) then
part.UsePartColor = true
end
info.Burnt = true
local w = Instance.new("Weld")
w.Part0 = part
w.Part1 = part:findFirstChild("HeatGlow")
w.Parent = w.Part0
end
if (info.PercentBurned >= 100) then markForDelete = true end
info.Glow.Material = Enum.Material.Neon
info.Glow.Transparency = 1-min(max(0,(info.Temperature-tempBeginGlow)/tempToMaxGlow),1)
info.Glow.Color = tempToColor3(info.Temperature*2)
info.Light.Brightness = min(max(0,(info.Temperature-tempBeginGlow)/tempToMaxGlow),1)+1
info.Light.Color = color1
info.DoRecalc = true
requiresRerun = true
else
--Get to ambient temperature
local s = part.Size
local surfaceArea = 2*(s.y*s.z+s.x*s.z+s.x*s.y)
local delta = (temp - info.Temperature) / max((part:GetMass() * matInfo.SpecificHeat * convectionMultiplier)/surfaceArea,1)
info.Temperature = info.Temperature + delta
info.Fire.Enabled = false
--0 is freezing point. Ice.
if (info.Temperature > 0) then
info.Glow.Material = Enum.Material.Neon
info.Glow.Transparency = 1-min(max(0,(info.Temperature-tempBeginGlow)/tempToMaxGlow),1)
info.Glow.Color = tempToColor3(info.Temperature*2)
else
info.Glow.Material = Enum.Material.Ice
info.Glow.Transparency = 1+max(info.Temperature/100,-1)
info.Glow.BrickColor = BrickColor.new("Pastel blue")
end
info.Light.Brightness = min(max(0,(info.Temperature-tempBeginGlow)/tempToMaxGlow),1)
info.Light.Color = tempToColor3(info.Temperature*2)
local rec = math.abs(ambientTemp - info.Temperature) > deltaTPartTransferThreshhold or math.abs(temp - info.Temperature) > deltaTPartTransferThreshhold
info.DoRecalc = rec
requiresRerun = requiresRerun or rec
end
for k,v in pairs(intersects) do
registerVoxelUpdate(k.x,k.y,k.z,info.Temperature,v)
--
registerVoxelUpdate(k.x,k.y+1,k.z,info.Temperature,v)
registerVoxelUpdate(k.x+1,k.y,k.z,info.Temperature,v)
registerVoxelUpdate(k.x-1,k.y,k.z,info.Temperature,v)
registerVoxelUpdate(k.x,k.y,k.z+1,info.Temperature,v)
registerVoxelUpdate(k.x,k.y,k.z-1,info.Temperature,v)
end
--Heat transfer between touching and connected parts
for _,p in pairs(part:GetTouchingParts()) do
local c,s = checkOBBVsOBB(part.CFrame,part.Size+vec3(0.2,0.2,0.2),p.CFrame,p.Size+vec3(0.2,0.2,0.2))
if (c and s>0 and parts[p]) then
local partTemp = parts[p].Temperature
local delta = (partTemp - info.Temperature) / max((part:GetMass() * matInfo.SpecificHeat * conductionMultiplierTouching)/s,1)
info.Temperature = info.Temperature + delta
if (abs(partTemp - info.Temperature) > deltaTPartTransferThreshhold) then parts[p].DoRerun = true requiresRerun = true end
end
end
for _,p in pairs(part:GetConnectedParts()) do
local c,s = checkOBBVsOBB(part.CFrame,part.Size+vec3(0.2,0.2,0.2),p.CFrame,p.Size+vec3(0.2,0.2,0.2))
if (c and s>0 and parts[p]) then
local partTemp = parts[p].Temperature
local delta = (partTemp - info.Temperature) / max((part:GetMass() * matInfo.SpecificHeat * conductionMultiplierTouching)/s,1)
info.Temperature = info.Temperature + delta
if (abs(partTemp - info.Temperature) > deltaTPartTransferThreshhold) then parts[p].DoRerun = true requiresRerun = true end
end
end
--Marked for deletion?
if (markForDelete) then
spawn(function()
parts[part] = nil
part.Transparency = 1
part.CanCollide = false
part.Anchored = false
part:ClearAllChildren()
local particles = script.BreakParticles:clone()
particles.Parent = part
wait(0.1)
particles:Emit(128)
local debris = game:GetService("Debris")
debris:AddItem(part,2)
end)
end
throttle(0.05,"Part updates")
end
if (part.Parent == nil) then
parts[part] = nil
end
end
return requiresRerun,calcs
end
--Connect to update triggers
updateIsRunning = false
function onUpdateTrigger()
if (updateIsRunning) then return end
updateIsRunning = true
local recalc1,c1 = true,0
local recalc2,c2 = true,0
while recalc1 or recalc2 do
local t = tick()
recalc1,c1 = doCalc()
recalc2,c2 = voxelTick()
if (doDebug) then
print("-------------------------")
print("Part updates: " .. c1)
print("Voxel updates: " .. c2)
print("Time to calc: " .. math.floor((tick()-t)*100e3)/100 .. " ms")
end
for _,a in pairs(game:GetService("Players"):GetPlayers()) do
if (damageCharacters and
a.Character and
a.Character:FindFirstChild("Torso") and
a.Character:FindFirstChild("Humanoid")) then
local intersects = getVoxelIntersects(a.Character.Torso)
local temp = 0
for k,v in pairs(intersects) do
local voxel = getVoxel(k.x,k.y,k.z)
temp = temp + v*voxel.Temperature
end
if (temp > charDamageThreshold) then
a.Character.Humanoid.Health = a.Character.Humanoid.Health - temp*charDamageMultiplier
end
end
end
wait()
end
updateIsRunning = false
end
--External run enables
local library = {}
--Method to set the temperature of a part
function library:SetPartTemperature(part,temp)
if (part == nil) then return end
if (parts[part] == nil) then registerParts(part) end
parts[part].Temperature = temp
parts[part].DoRecalc = true
onUpdateTrigger()
end
--Method to get the temperature of a part
function library:GetPartTemperature(part)
if (parts[part]) then return parts[part].Temperature end
end
--Setting voxel temperatures at world coordinates
function library:SetVoxelTemperature(x,y,z,temperature)
x,y,z = math.floor(x/4),math.floor(y/4),math.floor(z/4)
local vox = getVoxel(x,y,z)
vox.Temperature = temperature
setVoxel(x,y,z,vox)
end
--Getting voxel temperatures at world coordinates
function library:GetVoxelTemperature(x,y,z)
x,y,z = math.floor(x/4),math.floor(y/4),math.floor(z/4)
return getVoxel(x,y,z).Temperature
end
--Setting configuration options
function library:SetConfiguration(name,value)
local config = script.Configuration:FindFirstChild(name)
if (config) then
local type1 = type(config.Value)
local type2 = type(value)
if (type1 ~= type2) then
warn("Configuration on " .. name .. " could not be set: Type mismatch, expected " .. type1 .. ", got " .. type2)
return false
end
config.Value = value
return true
else
warn("Configuration on " .. name .. " could not be set: Configuration value does not exist.")
return false
end
end
--Reading configuration options
function library:GetConfiguration(name,value)
local config = script.Configuration:FindFirstChild(name)
if (config) then
return config.Value
else
warn("Could not get configuration on " .. name .. ": Configuration value does not exist.")
return nil
end
end
--Registering a whole model of parts
function library:RegisterParts(group)
registerParts(group)
end
--Getting a list of registered parts
function library:GetRegisteredParts()
local output = {}
for index,_ in pairs(parts) do output[#output+1] = index end
return output
end
--Registering individual parts
function library:RegisterPart(part)
registerPart(part)
end
--Checking if a part is registered
function library:IsPartRegistered(part)
return parts[part] ~= nil
end
--Removes a part from the simulation
function library:UnregisterPart(part)
if (part:FindFirstChild("HeatGlow")) then part.HeatGlow:Destroy() end
if (part:FindFirstChild("FireParticles")) then part.FireParticles:Destroy() end
parts[part] = nil
end
--Clears all parts from the simulation
function library:UnregisterAllParts()
for part,_ in pairs(parts) do
library:UnregisterPart(part)
end
end
--Function to clear all voxel's info
function library:ClearVoxels()
voxels = {}
end
--Players should be flammable :D
function onJoin(p)
p.Changed:connect(function(prop)
if (prop == "Character") then
wait(1)
print("Handling character for",p)
for _,a in pairs(p.Character:children()) do
if (a:IsA("BasePart")) then
library:SetPartTemperature(a,ambientTemp)
end
end
end
end)
end
game:GetService("Players").PlayerAdded:connect(onJoin)
for _,p in pairs(game:GetService("Players"):GetPlayers()) do
onJoin(p)
end
--Alrighty, go for it.
onUpdateTrigger()
--Make the exposed functions accessible externally
return library