init.lua 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. -- Minetest: builtin/item.lua (override falling entity with new features)
  2. -- override falling nodes to add damage
  3. local function add_fall_damage(node, damage)
  4. if core.registered_nodes[node] then
  5. local group = core.registered_nodes[node].groups
  6. group.falling_node_damage = damage
  7. core.override_item(node, {groups = group})
  8. else
  9. print (node .. " not found to add falling_node_damage to")
  10. end
  11. end
  12. add_fall_damage("default:sand", 2)
  13. add_fall_damage("default:desert_sand", 2)
  14. add_fall_damage("default:silver_sand", 2)
  15. add_fall_damage("default:gravel", 3)
  16. add_fall_damage("caverealms:coal_dust", 3)
  17. add_fall_damage("tnt:tnt_burning", 4)
  18. --
  19. -- Falling stuff
  20. --
  21. local node_fall_hurt = minetest.setting_getbool("node_fall_hurt") ~= false
  22. local delay = 0.1 -- used to simulate lag
  23. local gravity = core.settings:get("movement_gravity") or 9.81
  24. local function fall_hurt_check(self, pos)
  25. if self.hurt_toggle then
  26. -- Get damage level from falling_node_damage group
  27. local damage = core.registered_nodes[self.node.name] and
  28. core.registered_nodes[self.node.name].groups.falling_node_damage
  29. if damage then
  30. local all_objects = minetest.get_objects_inside_radius(pos, 0.8)
  31. for _,obj in ipairs(all_objects) do
  32. local name = obj:get_luaentity() and
  33. obj:get_luaentity().name or ""
  34. if name ~= "__builtin:item"
  35. and name ~= "__builtin:falling_node" then
  36. obj:punch(self.object, 4.0, {
  37. damage_groups = {fleshy = damage}
  38. })
  39. self.hurt_toggle = false
  40. end
  41. end
  42. end
  43. else
  44. self.hurt_toggle = true
  45. end
  46. end
  47. core.register_entity(":__builtin:falling_node", {
  48. initial_properties = {
  49. visual = "wielditem",
  50. visual_size = {x = 0.667, y = 0.667},
  51. textures = {},
  52. physical = true,
  53. is_visible = false,
  54. collide_with_objects = false,
  55. collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
  56. },
  57. set_node = function(self, node, meta)
  58. self.node = node
  59. self.meta = meta
  60. self.hurt_toggle = true
  61. self.object:set_properties({
  62. is_visible = true,
  63. textures = {node.name}
  64. })
  65. end,
  66. get_staticdata = function(self)
  67. return core.serialize({
  68. node = self.node,
  69. meta = self.meta
  70. })
  71. end,
  72. on_activate = function(self, staticdata)
  73. self.object:set_armor_groups({immortal = 1})
  74. self.object:set_acceleration({x = 0, y = -gravity, z = 0})
  75. local ds = core.deserialize(staticdata)
  76. if ds and ds.node then
  77. self:set_node(ds.node, ds.meta)
  78. elseif ds then
  79. self:set_node(ds)
  80. elseif staticdata ~= "" then
  81. self:set_node({name = staticdata})
  82. end
  83. end,
  84. on_step = function(self, dtime)
  85. -- used to simulate a little lag
  86. self.timer = (self.timer or 0) + dtime
  87. if self.timer < delay then
  88. return
  89. end
  90. self.timer = 0
  91. -- Set gravity and horizontal slowing
  92. self.object:set_acceleration({x = 0, y = -gravity, z = 0})
  93. local vel = self.object:get_velocity()
  94. vel.x = vel.x * 0.95
  95. vel.z = vel.z * 0.95
  96. if vel.x < 0.1 and vel.z < 0.1 then
  97. vel.x = 0
  98. vel.z = 0
  99. end
  100. self.object:set_velocity(vel)
  101. local pos = self.object:get_pos()
  102. -- Position of bottom center point
  103. local below_pos = {x = pos.x, y = pos.y - 0.7, z = pos.z}
  104. -- Check for player/mobs below falling node and hurt them >:D
  105. if node_fall_hurt then
  106. fall_hurt_check(self, below_pos)
  107. end
  108. -- check if falling node has custom function set
  109. local custom = core.registered_items[self.node.name]
  110. and core.registered_items[self.node.name].falling_step
  111. if custom and custom(self, pos, dtime + delay) == false then
  112. return -- skip further checks if false
  113. end
  114. -- Avoid bugs caused by an unloaded node below
  115. local below_node = core.get_node_or_nil(below_pos)
  116. -- Delete on contact with ignore at world edges or return if unloaded
  117. if not below_node then
  118. return
  119. elseif below_node.name == "ignore" then
  120. self.object:remove()
  121. return
  122. end
  123. local below_nodef = core.registered_nodes[below_node.name]
  124. -- Is it a level node we can add to?
  125. if below_nodef and below_nodef.leveled and
  126. below_node.name == self.node.name then
  127. local addlevel = self.node.level
  128. if not addlevel or addlevel <= 0 then
  129. addlevel = below_nodef.leveled
  130. end
  131. if core.add_node_level(below_pos, addlevel) == 0 then
  132. self.object:remove()
  133. return
  134. end
  135. end
  136. -- Stop node if it falls on walkable surface, or floats on water
  137. if (below_nodef and below_nodef.walkable == true)
  138. or (below_nodef
  139. and core.get_item_group(self.node.name, "float") ~= 0
  140. and below_nodef.liquidtype ~= "none") then
  141. self.object:set_velocity({x = 0, y = 0, z = 0})
  142. end
  143. -- Has the fallen node stopped moving ?
  144. if vector.equals(vel, {x = 0, y = 0, z = 0}) then
  145. local npos = self.object:get_pos()
  146. -- Get node we've landed inside
  147. local cnode = minetest.get_node(npos).name
  148. local cdef = core.registered_nodes[cnode]
  149. -- If air_equivalent or buildable_to or an attached_node then place
  150. -- node, otherwise drop falling node as an item instead.
  151. if (cdef and cdef.air_equivalent == true)
  152. or (cdef and cdef.buildable_to == true)
  153. or (cdef and cdef.liquidtype ~= "none")
  154. or core.get_item_group(cnode, "attached_node") ~= 0 then
  155. -- Are we an attached node ? (grass, flowers, torch)
  156. if core.get_item_group(cnode, "attached_node") ~= 0 then
  157. -- Add drops from attached node
  158. local drops = core.get_node_drops(cnode, "")
  159. for _, dropped_item in pairs(drops) do
  160. core.add_item(npos, dropped_item)
  161. end
  162. -- Run script hook
  163. for _, callback in pairs(core.registered_on_dignodes) do
  164. callback(npos, cnode)
  165. end
  166. end
  167. -- Round position
  168. npos = vector.round(npos)
  169. -- Place falling entity as node and write any metadata
  170. core.add_node(npos, self.node)
  171. if self.meta then
  172. local meta = core.get_meta(npos)
  173. meta:from_table(self.meta)
  174. end
  175. -- Play placed sound
  176. local def = core.registered_nodes[self.node.name]
  177. if def.sounds and def.sounds.place and def.sounds.place.name then
  178. core.sound_play(def.sounds.place, {pos = npos})
  179. end
  180. -- Just incase we landed on other falling nodes
  181. core.check_for_falling(npos)
  182. else
  183. -- Add drops from falling node
  184. local drops = core.get_node_drops(self.node, "")
  185. for _, dropped_item in pairs(drops) do
  186. core.add_item(npos, dropped_item)
  187. end
  188. end
  189. -- Remove falling entity if it cannot be placed
  190. self.object:remove()
  191. end
  192. end
  193. })
  194. --[[
  195. core.override_item("default:gravel", {
  196. falling_step = function(self, pos, dtime)
  197. print ("Gravel falling!", dtime)
  198. end
  199. })
  200. ]]