123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- local thrown_bobbers = {}
- local catchables = {}
- local baits = {}
- for k,v in pairs(minetest.registered_items) do
- if minetest.get_item_group(k, "fishing_catch") ~= 0 then
- table.insert(catchables, k)
- elseif minetest.get_item_group(k, "fishing_bait") ~= 0 then
- table.insert(baits, k)
- end
- end
- local function fishing(bobber, elapsed)
- bobber:get_luaentity()._since_bobber_in_water = bobber:get_luaentity()._since_bobber_in_water + elapsed
- -- Wait atleast 5 seconds
- if math.floor(bobber:get_luaentity()._since_bobber_in_water) > 5 then
- local pos = bobber:get_pos()
- if not bobber:get_luaentity()._there_is_fish_to_catch then
- bobber:get_luaentity()._there_is_fish_to_catch = math.random(1, 200) == 42
- if pos.y % 1 ~= 0.5 then
- pos.y = (pos.y - (pos.y % 1)) + 0.5
- bobber:move_to(pos)
- bobber:get_luaentity()._bobber_down = false
- bobber:get_luaentity()._bob_travel_time = 1
- end
- else
- bobber:get_luaentity()._the_fish_waited = bobber:get_luaentity()._the_fish_waited + elapsed
- -- Visualise the fish's presence
- -- Bob the bobber
- if bobber:get_luaentity()._bob_travel_time > 0 and not bobber:get_luaentity()._bobber_down then
- pos.y = pos.y - 0.02
- bobber:get_luaentity()._bob_travel_time = bobber:get_luaentity()._bob_travel_time - 0.1
- bobber:set_pos(pos)
- elseif bobber:get_luaentity()._bob_travel_time <= 0 and not bobber:get_luaentity()._bobber_down then
- bobber:get_luaentity()._bobber_down = true
- elseif bobber:get_luaentity()._bob_travel_time <= 1 and bobber:get_luaentity()._bobber_down then
- pos.y = pos.y + 0.02
- bobber:get_luaentity()._bob_travel_time = bobber:get_luaentity()._bob_travel_time + 0.1
- bobber:set_pos(pos)
- elseif bobber:get_luaentity()._bob_travel_time >= 1 and bobber:get_luaentity()._bobber_down then
- bobber:get_luaentity()._bobber_down = false
- end
- -- Spray bubbles
- minetest.add_particle({
- pos = {
- x=pos.x + math.random(-1,1) * math.random() / 2,
- y=pos.y + 0.1,
- z=pos.z + math.random(-1,1) * math.random() / 2
- },
- velocity = {
- x = 0,
- y = 2,
- z = 0
- },
- acceleration = {
- x = 0,
- y = -5,
- z = 0},
- expirationtime = math.random(),
- size = math.random() + 0.5,
- collisiondetection = true,
- vertical = false,
- texture = "particles_bubble.png",
- })
- -- Play sound
- if bobber:get_luaentity()._bob_travel_time >= 0.4 and bobber:get_luaentity()._bob_travel_time <= 0.5 then
- minetest.sound_play("default_water_footstep", {
- pos,
- max_hear_distance = 10,
- gain = 10.0,
- })
- end
- if bobber:get_luaentity()._the_fish_waited > 5 then
- bobber:get_luaentity()._there_is_fish_to_catch = false
- bobber:get_luaentity()._the_fish_waited = 0
- end
- end
- end
- end
- local function has_bait_in_inventory(player)
- local inv = player:get_inventory()
- for _,v in ipairs(baits) do
- if inv:contains_item("main", v) then
- return v
- end
- end
- return false
- end
- minetest.register_entity("fishing:bobber_entity", {
- textures = {"fishing_bobber.png"},
- visual_size = {x=0.5, y=0.5},
- pointable = false,
- walkable = false,
- physical = false,
- collisionbox = {-0.1, -0.5, -0.1, 0.1, 0.3, 0.1},
- _owner = "",
- _since_bobber_in_water = 0,
- _there_is_fish_to_catch = false,
- _the_fish_waited = 0,
- _bob_travel_time = 1,
- _bobber_down = false,
- on_step = function(self, elapsed)
- local pos = self.object:get_pos()
- pos.y = math.floor(pos.y)
- local node = minetest.get_node(pos).name
- local owner = minetest.get_player_by_name(self.object:get_luaentity()._owner)
- -- Stop the bobber if collides with node
- if (node ~= "air") and (self.object:get_luaentity()._since_bobber_in_water == 0) then
- self.object:set_acceleration({x=0,y=0,z=0})
- self.object:set_velocity({x=0,y=0,z=0})
- -- correcting the bobber's position so it is halfway submerged in the water
- pos.y = pos.y + 0.5
- self.object:move_to(pos)
- end
- if owner then
- --If the player is too far from the bobber remove it
- if owner:get_pos().x > (pos.x + 15) or owner:get_pos().x < (pos.x - 15) or
- owner:get_pos().y > (pos.y + 15) or owner:get_pos().y < (pos.y - 15) or
- owner:get_pos().z > (pos.z + 15) or owner:get_pos().z < (pos.z - 15) then
- self.object:remove()
- thrown_bobbers[owner:get_player_name()] = nil
- return
- end
- -- If the player puts away the rod remove the bobber
- if owner:get_wielded_item():get_name() ~= "fishing:fishing_rod" then
- self.object:remove()
- thrown_bobbers[owner:get_player_name()] = nil
- return
- end
- -- the process of fishing
- if node == "default:water_source" and has_bait_in_inventory(owner) then
- fishing(self.object, elapsed)
- end
- else
- --If the bobber doesn't have an owner remove it
- self.object:remove()
- return
- end
- end,
- })
- -- Remove bobber if player leaves the game
- minetest.register_on_leaveplayer(function(player)
- local player_name = player:get_player_name()
- if thrown_bobbers[player_name] then
- thrown_bobbers[player_name]:remove()
- thrown_bobbers[player_name] = nil
- end
- end)
- -- Remove bobber if player dies
- minetest.register_on_dieplayer(function(player)
- local player_name = player:get_player_name()
- if thrown_bobbers[player_name] then
- thrown_bobbers[player_name]:remove()
- thrown_bobbers[player_name] = nil
- end
- end)
- local function cast_fishing_rod(itemstack, player, pointing_at)
- local bobber_gravity = 6
- local bobber_velocity = 10
- local player_name = player:get_player_name()
- local player_inv = player:get_inventory()
- local pos = player:getpos()
- local dir = player:get_look_dir()
- -- Bobber starting position correction.
- pos.y = pos.y + 1.5
- if not thrown_bobbers[player_name] then
- thrown_bobbers[player_name] = minetest.add_entity(pos, "fishing:bobber_entity")
- thrown_bobbers[player_name]:get_luaentity()._owner = player_name
- thrown_bobbers[player_name]:set_velocity({
- x = dir.x * bobber_velocity,
- y = dir.y * bobber_velocity,
- z = dir.z * bobber_velocity
- })
- thrown_bobbers[player_name]:set_acceleration({
- x = dir.x * -3,
- y = -bobber_gravity,
- z = dir.z * -3
- })
- else
- if thrown_bobbers[player_name]:get_luaentity()._there_is_fish_to_catch then
- local rand_loot = math.random(1, table.getn(catchables))
- local catch = catchables[rand_loot]
- if player_inv:room_for_item("main", catch) then
- player_inv:add_item("main", catch)
- else
- minetest.add_item(pos, catch)
- end
- -- Pherhaps take bait if not in creative
- if math.random(1, 5) == 1 and not minetest.settings:get_bool("creative_mode") then
- player_inv:remove_item("main", has_bait_in_inventory(player))
- end
- end
- thrown_bobbers[player_name]:remove()
- thrown_bobbers[player_name] = nil
- if not minetest.settings:get_bool("creative_mode") then
- -- Wear down fishing_rod
- local idef = itemstack:get_definition()
- itemstack:add_wear(65536/100)
- if itemstack:get_count() == 0 and idef.sound and idef.sound.breaks then
- minetest.sound_play(idef.sound.breaks, {pos=player:get_pos(), gain=0.5}, true)
- end
- end
- end
- return itemstack
- end
- minetest.register_tool("fishing:fishing_rod", {
- description = "Fishing Rod",
- groups = { tool=1 },
- inventory_image = "fishing_fishing_rod.png",
- wield_image = "fishing_fishing_rod.png",
- wield_scale = { x = 1.5, y = 1.5, z = 1 },
- stack_max = 1,
- on_use = cast_fishing_rod,
- sound = { breaks = "default_tool_breaks" },
- })
- minetest.register_craft({
- output = "fishing:fishing_rod",
- recipe = {
- {"","","group:stick"},
- {"","group:stick","farming:string"},
- {"group:stick","","farming:string"},
- }
- })
- minetest.register_craft({
- type = "fuel",
- recipe = "fishing:fishing_rod",
- burntime = 15,
- })
|