]> git.lizzy.rs Git - Crafter.git/blob - mods/fire/init.lua
Overhaul fire
[Crafter.git] / mods / fire / init.lua
1 minetest.register_node("fire:fire", {
2     description = "Fire",
3     drawtype = "firelike",
4         tiles = {
5                 {
6                         name = "fire.png",
7                         animation = {
8                                 type = "vertical_frames",
9                                 aspect_w = 16,
10                                 aspect_h = 16,
11                                 length = 0.3
12                         },
13                 },
14         },
15         --inventory_image = "fire.png",
16     groups = {dig_immediate = 1,fire=1,hurt_inside=1},
17     sounds = main.stoneSound(),
18     floodable = true,
19     drop = "",
20     walkable = false,
21     is_ground_content = false,
22     light_source = 11, --debugging
23     on_construct = function(pos)
24                 local under = minetest.get_node(vector.new(pos.x,pos.y-1,pos.z)).name
25                 --makes nether portal
26                 if under == "nether:obsidian" then
27                         minetest.remove_node(pos)
28                         create_nether_portal(pos)
29                 --fire lasts forever on netherrack
30                 elseif under ~= "nether:netherrack" then
31                         local timer = minetest.get_node_timer(pos)
32                         timer:start(math.random(0,2)+math.random())
33                 end
34     end,
35     on_timer = function(pos, elapsed)
36             local find_flammable = minetest.find_nodes_in_area(vector.subtract(pos,1), vector.add(pos,1), {"group:flammable"})
37             --print(dump(find_flammable))
38             
39             for _,p_pos in pairs(find_flammable) do
40                     if math.random() > 0.9 then
41                                 minetest.set_node(p_pos,{name="fire:fire"})
42                                 local timer = minetest.get_node_timer(p_pos)
43                                 timer:start(math.random(0,2)+math.random())
44                         end
45             end
46             
47             if math.random() > 0.85 then
48                         minetest.remove_node(pos)
49                 else
50                         local timer = minetest.get_node_timer(pos)
51                         timer:start(math.random(0,2)+math.random())
52                 end
53     end,
54 })
55
56 --flint and steel
57 minetest.register_tool("fire:flint_and_steel", {
58         description = "Flint and Steel",
59         inventory_image = "flint_and_steel.png",
60         on_place = function(itemstack, placer, pointed_thing)
61                 if pointed_thing.type ~= "node" then
62                         return
63                 end
64                 if minetest.get_node(pointed_thing.above).name ~= "air" then
65                         minetest.sound_play("flint_failed", {pos=pointed_thing.above})
66                         return
67                 end
68                 
69                 --can't make fire in the aether
70                 if pointed_thing.above.y >= 20000 then
71                         minetest.sound_play("flint_failed", {pos=pointed_thing.above,pitch=math.random(75,95)/100})
72                         return
73                 end
74                 
75                 minetest.add_node(pointed_thing.above,{name="fire:fire"})
76                 minetest.sound_play("flint_and_steel", {pos=pointed_thing.above})
77                 itemstack:add_wear(100)
78                 return(itemstack)
79         end,
80         tool_capabilities = {
81                 groupcaps={
82                         _namespace_reserved = {times={[1]=5555}, uses=0, maxlevel=1},
83                 },
84         },
85         groups = {flint=1},
86         sound = {breaks = {name="tool_break",gain=0.4}},
87 })
88
89 minetest.register_craft({
90         type = "shapeless",
91         output = "fire:flint_and_steel",
92         recipe = {"main:flint","main:iron"},
93 })
94
95
96 fire_table = {}
97
98 local fire = {}
99
100 fire.initial_properties = {
101         hp_max = 1,
102         physical = false,
103         collide_with_objects = false,
104         collisionbox = {0, 0, 0, 0, 0, 0},
105         visual = "cube",
106         textures = {"nothing.png","nothing.png","fire.png","fire.png","fire.png","fire.png"},
107         visual_size = {x = 1, y = 1, z = 1},
108         --textures = {"nothing.png","nothing.png","fire.png","fire.png","fire.png","fire.png"},--, animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=8.0}},
109         is_visible = true,
110         pointable = false,
111 }
112
113 fire.on_activate = function(self)
114         local texture_list = {
115                 "nothing.png",
116                 "nothing.png",
117                 "fire.png^[opacity:180^[verticalframe:8:0",
118                 "fire.png^[opacity:180^[verticalframe:8:0",
119                 "fire.png^[opacity:180^[verticalframe:8:0",
120                 "fire.png^[opacity:180^[verticalframe:8:0",
121         }
122         self.object:set_properties({textures=texture_list})
123 end
124 --animation stuff
125 fire.frame = 0
126 fire.frame_timer = 0
127 fire.frame_update = function(self)
128         self.frame = self.frame + 1
129         if self.frame > 7 then
130                 self.frame = 0
131         end
132         local texture_list = {
133                 "nothing.png",
134                 "nothing.png",
135                 "fire.png^[opacity:180^[verticalframe:8:"..self.frame,
136                 "fire.png^[opacity:180^[verticalframe:8:"..self.frame,
137                 "fire.png^[opacity:180^[verticalframe:8:"..self.frame,
138                 "fire.png^[opacity:180^[verticalframe:8:"..self.frame,
139         }
140         self.object:set_properties({textures=texture_list})
141 end
142
143 fire.timer = 0
144 fire.life = 0
145 fire.on_step = function(self,dtime)     
146         --master is the flag of the entity that controls the hurt
147         --owner is the flag that tells the entity who to hurt
148         if self.owner and (self.owner:is_player() or self.owner:get_luaentity()) then
149                 if self.master then
150                         self.timer = self.timer + dtime
151                         self.life = self.life + dtime
152         
153                         if self.life >= 7 then
154                                 put_fire_out(self.owner)
155                                 self.object:remove()
156                                 return
157                         end
158                         
159                         if self.timer >= 1 then
160                                 self.timer = 0
161                                 if self.owner:is_player() then
162                                         self.owner:set_hp(self.owner:get_hp()-1)
163                                 elseif self.owner and self.owner:get_luaentity() then
164                                         self.owner:punch(self.object, 2, 
165                                                 {
166                                                 full_punch_interval=0,
167                                                 damage_groups = {damage=2},
168                                         })
169                                 end
170                         end
171                 end
172         else
173                 self.object:remove()
174         end
175         self.frame_timer = self.frame_timer + dtime
176         if self.frame_timer >= 0.015 then
177                 self.frame_timer = 0
178                 self.frame_update(self)
179         end
180 end
181 minetest.register_entity("fire:fire",fire)
182
183
184
185 --this is the handling part
186
187 local fire_channels = {}
188
189 minetest.register_on_joinplayer(function(player)
190         local name = player:get_player_name()
191         fire_channels[name] = minetest.mod_channel_join(name..":fire_state")
192
193         minetest.after(4,function()
194                 local meta = player:get_meta()
195                 if meta:get_int("on_fire") > 0 then
196                         start_fire(player)
197                 end
198         end)
199 end)
200
201 function start_fire(object)
202         if object:is_player() then
203                 local name = object:get_player_name()
204                 if not fire_table[name] then
205                         local obj = minetest.add_entity(object:get_pos(),"fire:fire")
206                         obj:get_luaentity().master = true
207                         obj:get_luaentity().owner = object
208                         obj:set_attach(object, "", vector.new(0,11,0),vector.new(0,0,0))
209                         obj:set_properties({visual_size=vector.new(1,2,1)})
210                         fire_table[name] = obj
211
212                         local meta = object:get_meta()
213                         fire_channels[name]:send_all("1")
214                         meta:set_int("on_fire", 1)
215                 end
216         elseif object and object:get_luaentity() then
217                 object:get_luaentity().on_fire = true
218                 local divisor = object:get_properties().visual_size.y
219                 local obj = minetest.add_entity(object:get_pos(),"fire:fire")
220                 --obj:set_properties
221                 obj:get_luaentity().master = true
222                 obj:get_luaentity().owner = object
223
224                 local fire_table = object:get_luaentity().fire_table
225                 obj:set_attach(object, "", fire_table.position,vector.new(0,0,0))
226                 obj:set_properties({visual_size=fire_table.visual_size})
227
228                 object:get_luaentity().fire_entity = obj
229         end
230 end
231
232 function put_fire_out(object)
233         if object:is_player() then
234                 local name = object:get_player_name()
235                 if fire_table[name] then
236                         local obj = fire_table[name]
237                         if obj:get_luaentity() then
238                                 obj:remove()
239                         end
240                         fire_table[name] = nil
241
242                         local meta = object:get_meta()
243                         fire_channels[name]:send_all("0")
244                         meta:set_int("on_fire", 0)
245                 end
246         elseif object and object:get_luaentity() then
247                 object:get_luaentity().on_fire = false
248                 object:get_luaentity().fire_entity = nil
249         end
250 end
251
252 minetest.register_on_respawnplayer(function(player)
253         put_fire_out(player)
254 end)