512 lines
No EOL
16 KiB
Lua
512 lines
No EOL
16 KiB
Lua
-- Extract particle graphics from a node texture
|
|
local function extract_tile(tiles,color)
|
|
if not tiles then
|
|
return "blank.png"
|
|
end
|
|
|
|
if not color and tiles.color then
|
|
color = tiles.color
|
|
end
|
|
|
|
if type(tiles[1]) == "string" then
|
|
return tiles[1], color
|
|
elseif type(tiles[1]) == "table" then
|
|
return tiles[1].name or tiles[1].image, color
|
|
else
|
|
return "blank.png"
|
|
end
|
|
end
|
|
|
|
local function extract_particles(tiles,color,coords)
|
|
tiles, color = extract_tile(tiles,color)
|
|
return tiles .. "^[resize:16x16^[sheet:8x8:" .. (coords or (math.random(0,7) .. "," .. math.random(0,7))) .. (color and ("^[multiply:" .. color) or "")
|
|
end
|
|
|
|
-- Get texture blend value
|
|
local blend_method = core.features.particle_blend_clip and "clip" or "alpha"
|
|
|
|
-- Dusty particles (sand, dry grass, etc.)
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:dusty",
|
|
check = function(self, pos)
|
|
return (pos.y < 0 or pos.y > 6) and core.get_node(pos:offset(0,1,0)).name == "air"
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local does_apply = (groups.stone and groups.stone > 0) or (groups.sand and groups.sand > 0) or (groups.everness_sand and groups.everness_sand > 0) or node:find("dry_") or node:find("clay") or node:find("gravel") or node:find("litter$") or node:find("podzol")
|
|
return does_apply and { "effervescence:floors" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(56,64),
|
|
time = 5,
|
|
pos = {
|
|
min = pos:add(vector.new(-6,0.575,-6)),
|
|
max = pos:add(vector.new(6,1,6)),
|
|
},
|
|
minsize = 0.2,
|
|
maxsize = 0.275,
|
|
minvel = { x = -1, y = -0.02, z = -1 },
|
|
maxvel = { x = 1, y = 0.02, z = 1 },
|
|
minexptime = 6,
|
|
maxexptime = 8,
|
|
minacc = {x = -1.5, y = 0, z = -1.5},
|
|
maxacc = {x = 1.5, y = 0.05, z = 1.5},
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Crumbly particles (falling bits of stone, dirt, gravel, etc.)
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:crumbly",
|
|
check = function(self, pos)
|
|
return core.get_node(pos:offset(0,-1,0)).name == "air"
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local does_apply = (groups.stone and groups.stone > 0) or (groups.crumbly and groups.crumbly > 0) or (groups.soil and groups.soil > 0) or node:find("gravel") or node:find("ore") or node:find("moss") or node:find(":dirt_")
|
|
return does_apply and { "effervescence:ceilings" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = 6,
|
|
time = 0.5,
|
|
pos = {
|
|
min = pos:add(vector.new(-0.45,-0.75,-0.45)),
|
|
max = pos:add(vector.new(0.45,-0.9,0.45)),
|
|
},
|
|
minvel = {x = 0, y = -5, z = 0},
|
|
maxvel = {x = -0.1, y = -7, z = -0.1},
|
|
minacc = {x = -0.1, y = -2, z = -0.1},
|
|
maxacc = {x = 0.1, y = -3, z = 0.1},
|
|
minexptime = 0.25,
|
|
maxexptime = 1,
|
|
minsize = 0.25,
|
|
maxsize = 1.25,
|
|
glow = ndef.glow or ndef.light_source,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Bustling particles (bit of grasses and mosses lifting off the ground)
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:bustling",
|
|
check = function(self, pos)
|
|
return core.get_node(pos:offset(0,1,0)).name == "air"
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local does_apply = node:find("grass") or node:find("moss") or node:find("lichen") or node:find("^ethereal:.+_dirt$") or node:find("litter$") or node:find("mycelium")
|
|
return does_apply and { "effervescence:floors" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(40,48),
|
|
time = 6,
|
|
pos = {
|
|
min = pos:add(vector.new(-8,0.5,-8)),
|
|
max = pos:add(vector.new(8,0.75,8)),
|
|
},
|
|
minvel = {x = -0.5, y = 0.1, z = -0.5},
|
|
maxvel = {x = 0.5, y = 0.175, z = 0.5},
|
|
minacc = {x = -0.325, y = 0.325, z = -0.325},
|
|
maxacc = {x = 0.325, y = 0.5, z = 0.325},
|
|
minexptime = 6,
|
|
maxexptime = 12,
|
|
minsize = 0.25,
|
|
maxsize = 0.375,
|
|
glow = ndef.glow or ndef.light_source,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Snowy particles (snowflakes gusting up from the ground)
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:snowy",
|
|
check = function(self, pos)
|
|
return core.get_node(pos:offset(0,1,0)).name == "air"
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local is_snow = (groups.snowy and groups.snowy > 0) or node:find(":snow") or node:find("_with_snow")
|
|
if is_snow then
|
|
return { def.drawtype == "nodebox" and "effervescence:rare" or "effervescence:floors" }
|
|
else
|
|
return nil
|
|
end
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(8,40),
|
|
time = 2,
|
|
pos = {
|
|
min = pos:add(vector.new(-3,0,-3)),
|
|
max = pos:add(vector.new(3,0.4,3)),
|
|
},
|
|
minvel = {x = -4, y = 2, z = -4},
|
|
maxvel = {x = 4, y = 3, z = 4},
|
|
minacc = {x = -1.75, y = 1, z = -1.75},
|
|
maxacc = {x = 1.75, y = 1.5, z = 1.75},
|
|
minexptime = 3,
|
|
maxexptime = 5,
|
|
minsize = 0.175,
|
|
maxsize = 0.225,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Leafy particles (falling leaves and snow on leaves)
|
|
local leaves = {
|
|
air = true, -- special exception for easier check logic
|
|
}
|
|
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:leafy",
|
|
check = function(self, pos)
|
|
local below = core.get_node(pos:offset(0,-1,0)).name
|
|
return leaves[below]
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local is_leaves = groups.leaves and groups.leaves > 0
|
|
if is_leaves then
|
|
leaves[node] = true
|
|
return { "effervescence:few" }
|
|
elseif node:find(":snow$") then
|
|
return { "effervescence:many" }
|
|
else
|
|
return nil
|
|
end
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(1,2),
|
|
time = 3,
|
|
pos = {
|
|
min = pos:add(vector.new(-0.45,-0.3,-0.45)),
|
|
max = pos:add(vector.new(0.45,-0.475,0.45)),
|
|
},
|
|
minvel = {x = -1, y = -0.75, z = -1},
|
|
maxvel = {x = 1, y = -1.5, z = 1},
|
|
minacc = {x = -0.75, y = -1, z = -0.75},
|
|
maxacc = {x = 0.75, y = -1.5, z = 0.75},
|
|
minexptime = 4,
|
|
maxexptime = 6,
|
|
minsize = 1,
|
|
maxsize = 1.5,
|
|
glow = ndef.glow or ndef.light_source,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Blossoming particles (flower petals on the breeze)
|
|
local colors = {
|
|
black = "#000000",
|
|
white = "#ffffff",
|
|
blue = "#1f75fe",
|
|
cyan = "#00b7eb",
|
|
orange = "#ff8c00",
|
|
yellow = "#ffd700",
|
|
purple = "#6f2da8",
|
|
violet = "#6f2da8",
|
|
magenta = "#ff33cc",
|
|
red = "#ff2400",
|
|
pink = "#ffc0cb",
|
|
green = "#7cfc00",
|
|
dark_green = "#013220",
|
|
dark_gray = "#333333",
|
|
darkgray = "#333333",
|
|
grey = "#9a9a9a",
|
|
brown = "#704214",
|
|
}
|
|
|
|
local flowers = { -- special cases listed here
|
|
["farming:sunflower_8"] = "#ffd700",
|
|
["farming:cotton_8"] = "#ffffff",
|
|
["x_farming:cotton_8"] = "#ffffff",
|
|
["dorwinion:dorwinion_glow_leaves"] = "self",
|
|
["nightshade:nightshade_glowin_leaves_1"] = "self",
|
|
["naturalbiomes:heatherflowernode"] = "self",
|
|
["naturalbiomes:heatherflower2node"] = "self",
|
|
["naturalbiomes:heatherflower3node"] = "self",
|
|
["naturalbiomes:heatherflower4node"] = "self",
|
|
}
|
|
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:blossoming",
|
|
check = function(self, pos)
|
|
return core.get_node(pos:offset(0,1,0)).name == "air"
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local is_plant = not def.walkable and def.drawtype:find("plant") and not node:find("shroom") and ((groups.flower and groups.flower > 0) or node:find("flower"))
|
|
if is_plant then
|
|
local dye = core.get_craft_result({
|
|
method = "normal",
|
|
width = 1,
|
|
items = { node },
|
|
})
|
|
if not dye.item:is_empty() and dye.item:get_name():find("dye") then
|
|
local dgroups = core.registered_items[dye.item:get_name()].groups
|
|
for color,hex in pairs(colors) do
|
|
if (dgroups["color_" .. color] and dgroups["color_" .. color] > 0) or (dgroups["basecolor_" .. color] and dgroups["basecolor_" .. color] > 0) then
|
|
flowers[node] = hex
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return flowers[node] and { "effervescence:many" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(2,3),
|
|
time = 1,
|
|
pos = {
|
|
min = pos:add(vector.new(-0.25,-0.125,-0.25)),
|
|
max = pos:add(vector.new(0.25,0.25,0.25)),
|
|
},
|
|
minvel = {x = -3, y = -0.05, z = -3},
|
|
maxvel = {x = 3, y = 1.5, z = 3},
|
|
minacc = {x = -0.125, y = -0.125, z = -0.125},
|
|
maxacc = {x = 0.125, y = 0.75, z = 0.125},
|
|
minexptime = 3,
|
|
maxexptime = 5,
|
|
minsize = 0.375,
|
|
maxsize = 0.5,
|
|
glow = ndef.glow or ndef.light_source,
|
|
texture = {
|
|
name = extract_particles(flowers[node.name] == "self" and ndef.tiles or {[1] = "effervescence_petals.png"},flowers[node.name] ~= "self" and flowers[node.name]),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Sporogenic particles (primarily mushrooms, glow worms, and certain vines)
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:sporogenic",
|
|
check = function(self, pos)
|
|
return true
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local does_apply = not def.walkable and def.drawtype:find("plant") and (node:find("glow_worm") or node:find("shroom") or node:find("fung") or node:find("myc") or node:find("coral_grass") or node:find("coral_plant") or node:find("[:_]vine") or node:find("spore") or (groups.mushroom and groups.mushroom > 0))
|
|
return does_apply and { "effervescence:many" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(9,12),
|
|
time = 1.5,
|
|
pos = {
|
|
min = pos:add(vector.new(-0.25,-0.1,-0.25)),
|
|
max = pos:add(vector.new(0.25,0.1,0.25)),
|
|
},
|
|
minvel = {x = -0.625, y = -0.075, z = -0.625},
|
|
maxvel = {x = 0.625, y = -0.05, z = 0.625},
|
|
minacc = {x = 0, y = -0.25, z = 0},
|
|
maxacc = {x = 0, y = -0.125, z = 0},
|
|
minexptime = 5,
|
|
maxexptime = 8,
|
|
minsize = 0.25,
|
|
maxsize = 0.325,
|
|
glow = ndef.glow or ndef.light_source or 2,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color,"4,7"),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Sparkly particles (glistening crystals or ice)
|
|
local neighbors = {
|
|
vector.new(0,1,0),
|
|
vector.new(1,0,0),
|
|
vector.new(0,0,1),
|
|
vector.new(-1,0,0),
|
|
vector.new(0,0,-1),
|
|
vector.new(0,-1,0),
|
|
}
|
|
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:sparkly",
|
|
check = function(self, pos)
|
|
for _,direction in ipairs(neighbors) do
|
|
if core.get_node(pos:add(direction)).name == "air" then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local does_apply = (def.drawtype:find("plant") and (node:find("[:_]crystal") or node:find("[:_]gem") or node:find("^caverealms:spike$") or node:find("icicle")) or node:find("[:_]ice$") or node:find("[:_]cave_ice$"))
|
|
return does_apply and { "effervescence:many" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(9,11),
|
|
time = 4,
|
|
pos = {
|
|
min = pos:add(vector.new(-0.75,-0.25,-0.75)),
|
|
max = pos:add(vector.new(0.75,0.575,0.75)),
|
|
},
|
|
minvel = {x = 0, y = -0.05, z = 0},
|
|
maxvel = {x = 0, y = 0, z = 0},
|
|
minacc = {x = 0, y = 0, z = 0},
|
|
maxacc = {x = 0, y = 0, z = 0},
|
|
minexptime = 3,
|
|
maxexptime = 6,
|
|
minsize = 0.1,
|
|
maxsize = 0.2,
|
|
glow = ndef.glow or ndef.light_source or 2,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,nil,"4,7") .. "^[sheet:4x4:1,1^[opacity:255^[brighten",
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Tiny bubbles at the surface of water
|
|
effervescence.register_environmental_particles({
|
|
name = "effervescence:bubbling",
|
|
check = function(self, pos)
|
|
return core.get_node(pos:offset(0,1,0)).name == "air"
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local does_apply = (def.liquidtype == "source" and node:find("[:_]water"))
|
|
return does_apply and { "effervescence:liquid_surface" }
|
|
end,
|
|
emit = function(self, pos)
|
|
local node = core.get_node(pos)
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(4,6),
|
|
time = math.random(3,4),
|
|
pos = {
|
|
min = pos:add(vector.new(-0.45,0.5,-0.45)),
|
|
max = pos:add(vector.new(0.45,0.525,0.45)),
|
|
},
|
|
minvel = {x = -0.0275, y = -0.025, z = -0.0275},
|
|
maxvel = {x = 0.0275, y = 0, z = 0.0275},
|
|
minacc = {x = 0, y = 0, z = 0},
|
|
maxacc = {x = 0, y = 0, z = 0},
|
|
minexptime = 1,
|
|
maxexptime = 2,
|
|
minsize = 1,
|
|
maxsize = 1.25,
|
|
glow = ndef.glow or ndef.light_source,
|
|
texture = extract_particles(ndef.tiles,ndef.color) .. "^[brighten^[opacity:127",
|
|
collisiondetection = false,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
})
|
|
|
|
-- Player walk particles (bits of dirt, snow, etc. kicked up underfoot)
|
|
local walking_nodes = {}
|
|
|
|
effervescence.register_player_particles({
|
|
name = "effervescence:walking",
|
|
check = function(self, player)
|
|
local velocity = player:get_velocity()
|
|
if math.abs(velocity.x) > 0.025 or math.abs(velocity.z) > 0.025 then
|
|
local below = core.get_node(player:get_pos():offset(0,-0.1,0)).name
|
|
return walking_nodes[below]
|
|
end
|
|
end,
|
|
applies_to = function(self, node, def)
|
|
local groups = def.groups or {}
|
|
local does_apply = (groups.crumbly and groups.crumbly > 0) or (groups.soil and groups.soil > 0) or (groups.sand and groups.sand > 0) or (groups.leaves and groups.leaves > 0) or (groups.snowy and groups.snowy > 0) or node:find(":snow") or node:find("_with_snow")
|
|
if does_apply then
|
|
walking_nodes[node] = true
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end,
|
|
emit = function(self, player)
|
|
local pos = player:get_pos()
|
|
local node = core.get_node(pos:offset(0,-0.1,0))
|
|
local ndef = core.registered_nodes[node.name]
|
|
return {
|
|
amount = math.random(3,4),
|
|
time = 0.25,
|
|
pos = {
|
|
min = pos:add(vector.new(-0.45,0.175,-0.45)),
|
|
max = pos:add(vector.new(0.45,0.275,0.45)),
|
|
},
|
|
minvel = {x = -1, y = 0.75, z = -1},
|
|
maxvel = {x = 1, y = 1, z = 1},
|
|
minacc = {x = 0, y = -9.81, z = 0},
|
|
maxacc = {x = 0, y = -9.81, z = 0},
|
|
minexptime = 1,
|
|
maxexptime = 1,
|
|
minsize = 0.75,
|
|
maxsize = 1,
|
|
glow = ndef.glow or ndef.light_source,
|
|
texture = {
|
|
name = extract_particles(ndef.tiles,ndef.color),
|
|
blend = blend_method,
|
|
},
|
|
collisiondetection = true,
|
|
collision_removal = true,
|
|
vertical = false,
|
|
}
|
|
end,
|
|
}) |