]> git.lizzy.rs Git - Crafter.git/blob - mods/bow/init.lua
Overhaul arrows
[Crafter.git] / mods / bow / init.lua
1 local arrow = {}
2 arrow.initial_properties = {
3         physical = true,
4         collide_with_objects = false,
5         collisionbox = {-0.05, -0.05, -0.05, 0.05, 0.05, 0.05},
6         visual = "mesh",
7         visual_size = {x = 1 , y = 1},
8         mesh = "basic_bow_arrow.b3d",
9         textures = {
10                 "basic_bow_arrow_uv.png"
11         },
12         pointable = true,
13         glow = -1,
14         --automatic_face_movement_dir = 0.0,
15         --automatic_face_movement_max_rotation_per_sec = 600,
16 }
17 arrow.on_activate = function(self, staticdata, dtime_s)
18         --self.object:set_animation({x=0,y=180}, 15, 0, true)
19         self.object:set_acceleration(vector.new(0,-9.81,0))
20 end
21
22 local radians_to_degrees = function(radians)
23         return(radians*180.0/math.pi)
24 end
25 arrow.spin = 0
26 arrow.owner = ""
27 arrow.stuck = false
28
29 arrow.on_step = function(self, dtime,moveresult)
30         local pos = self.object:get_pos()
31     local vel = self.object:get_velocity()
32
33     for _,object in ipairs(minetest.get_objects_inside_radius(pos, 2)) do
34                 if (object:is_player() and object:get_hp() > 0 and object:get_player_name() ~= self.thrower) or (object:get_luaentity() and object:get_luaentity().mob == true) then
35             if (object:is_player() and object:get_player_name() ~= self.owner) or (object:get_luaentity() and object:get_luaentity().mob == true) then
36                 object:punch(self.object, 2, 
37                     {
38                     full_punch_interval=1.5,
39                     damage_groups = {damage=3},
40                                 })
41                                 hit = true
42                                 self.object:remove()
43                                 break
44             end
45                 end
46         end
47         
48         if moveresult and moveresult.collides and self.stuck == false then
49
50                 if moveresult.collisions[1].new_velocity.x == 0 and moveresult.collisions[1].old_velocity.x ~= 0 then
51                         self.check_dir = vector.direction(vector.new(pos.x,0,0),vector.new(moveresult.collisions[1].node_pos.x,0,0))
52                 elseif moveresult.collisions[1].new_velocity.y == 0 and moveresult.collisions[1].old_velocity.y ~= 0 then
53                         self.check_dir = vector.direction(vector.new(0,pos.y,0),vector.new(0,moveresult.collisions[1].node_pos.y,0))
54                 elseif moveresult.collisions[1].new_velocity.z == 0 and moveresult.collisions[1].old_velocity.z ~= 0 then
55                         self.check_dir = vector.direction(vector.new(0,0,pos.z),vector.new(0,0,moveresult.collisions[1].node_pos.z))
56                 end
57
58                 minetest.sound_play("arrow_hit",{object=self.object,gain=1,pitch=math.random(80,100)/100,max_hear_distance=64})
59                 self.stuck = true
60                 self.object:set_velocity(vector.new(0,0,0))
61                 self.object:set_acceleration(vector.new(0,0,0))
62         elseif self.stuck == true and self.check_dir then
63                 local pos2 = vector.add(pos,vector.multiply(self.check_dir,0.2))
64
65                 minetest.add_particle({
66                         pos = pos2,
67                         velocity = {x=0, y=0, z=0},
68                         acceleration = {x=0, y=0, z=0},
69                         expirationtime = 0.2,
70                         size = 1,
71                         texture = "dirt.png",
72                 })
73                 
74                 local ray = minetest.raycast(pos, pos2, false, false)
75                 local pointed_thing = ray:next()
76
77                 if not pointed_thing then
78                         self.stuck = false
79                         self.object:set_acceleration(vector.new(0,-9.81,0))
80                 end
81         end
82         
83         if not self.stuck and pos and self.oldpos then
84                 self.spin = self.spin + (dtime*10)
85                 if self.spin > math.pi then
86                         self.spin = -math.pi
87                 end
88
89                 local dir = vector.normalize(vector.subtract(pos,self.oldpos))
90                 local y = minetest.dir_to_yaw(dir)
91                 local x = (minetest.dir_to_yaw(vector.new(vector.distance(vector.new(pos.x,0,pos.z),vector.new(self.oldpos.x,0,self.oldpos.z)),0,pos.y-self.oldpos.y))+(math.pi/2))
92                 self.object:set_rotation(vector.new(x,y,self.spin))
93                 --local frame = self.get_animation_frame(dir)
94                 --self.object:set_animation({x=frame, y=frame}, 0)
95         end
96         if self.stuck == false then
97                 self.oldpos = pos
98                 self.oldvel = vel
99         end
100 end
101 minetest.register_entity("bow:arrow", arrow)
102
103
104 minetest.register_craftitem("bow:bow_empty", {
105         description = "Bow",
106         inventory_image = "bow.png",
107         stack_max = 1,
108         groups = {bow=1}
109 })
110
111 for i = 1,5 do
112         minetest.register_craftitem("bow:bow_"..i, {
113                 description = "Bow",
114                 inventory_image = "bow_"..i..".png",
115                 stack_max = 1,
116                 groups = {bow=1,bow_loaded=i}
117         })
118 end
119
120 minetest.register_craftitem("bow:arrow", {
121         description = "Arrow",
122         inventory_image = "arrow_item.png",
123 })
124
125 minetest.register_globalstep(function(dtime)
126         --check if player has bow
127         for _,player in ipairs(minetest.get_connected_players()) do
128                 local item = player:get_wielded_item():get_name()
129                 if minetest.get_item_group(item, "bow") > 0 then
130                         --begin to pull the bow back
131                         if player:get_player_control().RMB == true then
132                                         local meta = player:get_meta()
133                                         local animation = meta:get_float("bow_loading_animation")
134                                         
135                                         if animation <= 5 then
136                                         
137                                                 if animation == 0 then
138                                                         animation = 1
139                                                         player:set_wielded_item(ItemStack("bow:bow_1"))
140                                                 end
141                                                 animation = animation + (dtime*2)
142                                                 
143                                                 --print(animation)
144                                                 
145                                                 meta:set_float("bow_loading_animation", animation)
146                                                 
147                                                 local level = minetest.get_item_group(item, "bow_loaded")
148                                                 
149                                                 
150                                                 local new_level = math.floor(animation + 0.5)
151                                                 
152                                                 --print(new_level,level)
153                                                 
154                                                 if new_level > level then
155                                                         if level > 0 then
156                                                                 minetest.sound_play("bow_pull_back", {object=player, gain = 1.0, max_hear_distance = 60,pitch = 0.7+new_level*0.1})
157                                                         end
158                                                         player:set_wielded_item(ItemStack("bow:bow_"..new_level))
159                                                 end
160                                         end
161                                         
162                                         --player:set_wielded_item(ItemStack("main:glass"))
163                         else
164                                 local power = minetest.get_item_group(item, "bow_loaded")
165                                 
166                                 if power > 0 then
167                                         local dir = player:get_look_dir()
168                                         local vel = vector.multiply(dir,power*10)
169                                         local pos = player:get_pos()
170                                         pos.y = pos.y + 1.625
171                                         local object = minetest.add_entity(pos,"bow:arrow")
172                                         object:set_velocity(vel)
173                                         object:get_luaentity().owner = player:get_player_name()
174                                         minetest.sound_play("bow", {object=player, gain = 1.0, max_hear_distance = 60,pitch = math.random(80,100)/100})
175                                 end
176                         
177                                 player:set_wielded_item(ItemStack("bow:bow_empty"))
178                                 local meta = player:get_meta()
179                                 meta:set_float("bow_loading_animation", 0)
180                         end
181                 end
182         end
183 end)