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