init.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. local special_leaves = dofile(minetest.get_modpath("leaves_in_the_wind").."/special_leaves.lua")
  2. local pi_over2 = (math.pi/2)
  3. local _3pi_over2 = 3*pi_over2
  4. local ppos, pyaw, dx, dz, yaw, isBehind -- Allocate
  5. minetest.register_abm({
  6. interval = 30,
  7. chance = 5,
  8. catch_up = false,
  9. nodenames = {"group:leaves"},
  10. action = function(npos, node, ...)
  11. if not minetest.registered_nodes[node.name] then return end
  12. npos.y = npos.y - 1
  13. local in_node = minetest.registered_nodes[minetest.get_node(npos).name]
  14. if in_node then
  15. if in_node.walkable then return end
  16. else
  17. return
  18. end
  19. --print(minetest.pos_to_string(npos))
  20. local particle = { --Default leaf particle
  21. pos = {x=npos.x+0.1,y=npos.y+0.25,z=npos.z+0.1},
  22. -- If these aren't floats, for some reason, particles will end up in the corners of nodes.
  23. texture = "(single_leaf_texture_mask"..math.random(1,2)..".png^[mask:"..
  24. -- Take this leaf's texture and mask it with the shape of a single leaf
  25. (minetest.registered_nodes[node.name].tiles[1] or "default_leaves.png")..
  26. ")^[transform"..math.random(0,7), --Flip it around for some randomness
  27. velocity = {
  28. x=math.sin((os.clock()%2000)/80)*0.25,
  29. y = -0.6,
  30. z=math.sin((os.clock()%2000)/80)*0.33,
  31. },
  32. size=2,
  33. expirationtime = 24,
  34. collisiondetection = true,
  35. collision_removal = true,
  36. vertical = false,
  37. leaf_spawn_chance = 70,
  38. spawn_radius = 44
  39. }
  40. local override = special_leaves[node.name]
  41. if type(override) == "table" then
  42. for k,v in pairs(override) do
  43. particle[k] = v
  44. end
  45. end
  46. for k,v in pairs(particle) do
  47. if type(v) == "function" then
  48. -- since values in tables are static,
  49. -- and we often want things to be a bit more random,
  50. -- let particles implement a function call.
  51. particle[k] = v(particle, npos, node, ...)
  52. end
  53. end
  54. if math.abs(particle.velocity.x) < 0.01 or math.abs(particle.velocity.z) < 0.01 then
  55. particle.collision_removal = false
  56. -- Collision seems to get confused if particles are moving very slowly.
  57. -- I'm not sure why, but frankly, I'm sick of working with engine code,
  58. -- so here's me chickening out instead.
  59. end
  60. if particle.leaf_spawn_chance >= 1 and math.random() < (1/particle.leaf_spawn_chance) then
  61. for _,player in pairs(minetest.get_connected_players()) do
  62. ppos = player:get_pos()
  63. pyaw = player:get_look_horizontal()
  64. dx = (ppos.x-npos.x)
  65. dz = (ppos.z-npos.z)
  66. isBehind = true
  67. yaw = nil
  68. if dz<0 then
  69. yaw = -math.atan(dx/dz)
  70. elseif dz>0 then
  71. yaw = math.pi-math.atan(dx/dz)
  72. elseif dx<0 then
  73. yaw = 0
  74. else
  75. yaw = math.pi
  76. end
  77. if yaw then
  78. local yaw_diff = ((yaw - pyaw)%(2*math.pi))
  79. isBehind = (yaw_diff > pi_over2) and (yaw_diff < _3pi_over2)
  80. end
  81. if math.sqrt(
  82. math.sqrt(dx^2 + dz^2)^2 -- Horizontal hypotenuse
  83. +
  84. (ppos.y-npos.y)^2
  85. ) <= (isBehind and (particle.spawn_radius/4) or particle.spawn_radius) then -- Reduce spawn radius significantly behind the player
  86. particle.playername = player:get_player_name()
  87. minetest.add_particle(table.copy(particle))
  88. end
  89. end
  90. end
  91. end,
  92. })