123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- --[[
- This fishing routine is inspired by the great work Rootyjr did for MineClone2
- ]]--
- local S = ethereal.intllib
- local fish_items = {
- "ethereal:fish_bluefin",
- "ethereal:fish_blueram",
- "ethereal:fish_catfish",
- "ethereal:fish_plaice",
- "ethereal:fish_salmon",
- {"ethereal:fish_clownfish", "savanna"},
- {"ethereal:fish_pike", "grassy"},
- {"ethereal:fish_flathead", "jungle"},
- {"ethereal:fish_pufferfish", "desert_ocean"},
- {"ethereal:fish_cichlid", "junglee_ocean"},
- {"ethereal:fish_coy", "sakura"},
- {"ethereal:fish_angler", "ocean"},
- {"ethereal:fish_jellyfish", "ocean"},
- {"ethereal:fish_seahorse", "ocean"},
- {"ethereal:fish_piranha", "jungle"},
- {"ethereal:fish_trout", "ocean"}
- }
- local junk_items = {
- "ethereal:bowl",
- "default:stick",
- "farming:string",
- "default:papyrus",
- "dye:black",
- {"ethereal:bamboo", "bamboo"}
- }
- local bonus_items = {
- "mobs:nametag",
- "mobs:saddle",
- "flowers:waterlily",
- "default:book",
- {"ethereal:crystal_spike", "frost"},
- {"ethereal:banana_bunch", "grove"}
- }
- local default_item = "default:dirt"
- local random = math.random -- yup we use this a lot
- -- add item function
- ethereal.add_item = function(fish, junk, bonus)
- if fish and fish ~= "" then
- table.insert(fish_items, fish)
- end
- if junk and junk ~= "" then
- table.insert(junk_items, junk)
- end
- if bonus and bonus ~= "" then
- table.insert(bonus_items, bonus)
- end
- end
- local effect = function(pos)
- minetest.add_particle({
- pos = {
- x = pos.x + random() - 0.5,
- y = pos.y + 0.1,
- z = pos.z + random() - 0.5
- },
- velocity = {x = 0, y = 4, z = 0},
- acceleration = {x = 0, y = -5, z = 0},
- expirationtime = random() * 0.5,
- size = random(),
- collisiondetection = false,
- vertical = false,
- texture = "bubble.png"
- })
- end
- -- fishing bob entity
- minetest.register_entity("ethereal:bob_entity", {
- textures = {"ethereal_fishing_bob.png"},
- visual_size = {x = 0.5, y = 0.5},
- collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
- physical = false,
- pointable = false,
- static_save = false,
- timer = 0,
- on_step = function(self, dtime)
- local pos = self.object:get_pos()
- local node = minetest.get_node(pos)
- local def = minetest.registered_nodes[node.name]
- -- casting rod into water
- if not self.cast then
- -- remove if we hit something hard
- if (def and def.walkable) or node.name == "ignore" then
- self.object:remove() ; --print("-- hit block")
- return
- end
- -- while bob is in water
- if def and def.liquidtype == "source"
- and minetest.get_item_group(node.name, "water") > 0 then
- -- incase of lag find water level
- local free_fall, blocker = minetest.line_of_sight(
- {x = pos.x, y = pos.y + 2, z = pos.z},
- {x = pos.x, y = pos.y , z = pos.z})
- -- do we have worms for bait, if so take one
- local player = self.fisher and minetest.get_player_by_name(self.fisher)
- local inv = player and player:get_inventory()
- local bait = 0
- if inv and inv:contains_item("main", "ethereal:worm") then
- inv:remove_item("main", "ethereal:worm")
- bait = 20
- end
- -- re-position fishing bob and set to cast
- pos = {x = pos.x, y = blocker.y + 0.45, z = pos.z}
- self.object:set_acceleration({x = 0, y = 0, z = 0})
- self.object:set_velocity({x = 0, y = 0, z = 0})
- self.object:set_pos(pos)
- self.bait = bait
- self.cast = true
- -- splash
- effect(pos) ; effect(pos) ; effect(pos) ; effect(pos)
- minetest.sound_play("default_water_footstep", {
- pos = pos, gain = 0.1}, true)
- end
- else -- already cast and waiting for fish
- -- we need a name
- if self.fisher == nil or self.fisher == "" then
- self.object:remove() ; --print("-- no name")
- return
- end
- local player = minetest.get_player_by_name(self.fisher)
- -- we need an actual person
- if not player then
- self.object:remove() ; --print("-- no player")
- return
- end
- local wield = player:get_wielded_item()
- -- we also need a rod to fish with
- if not wield or wield:get_name() ~= "ethereal:fishing_rod" then
- self.object:remove() ; --print("-- no rod")
- return
- end
- -- remove bob if player is too far away
- local pla_pos = player:get_pos()
- if (pla_pos.y - pos.y) > 15
- or (pla_pos.y - pos.y) < -15
- or (pla_pos.x - pos.x) > 15
- or (pla_pos.x - pos.x) < -15
- or (pla_pos.z - pos.z) > 15
- or (pla_pos.z - pos.z) < -15 then
- self.object:remove() ; --print("-- out of range")
- return
- end
- -- when in water, bob.
- if def and def.liquidtype == "source"
- and minetest.get_item_group(def.name, "water") ~= 0 then
- self.old_y = self.old_y or pos.y
- -- choose random time to wait (minus bait time for worm)
- if not self.patience or self.patience <= 0 then
- self.patience = random(10, (45 - self.bait))
- self.bait = 0
- end
- -- add particles if bobber bobbing
- if self.bob then
- effect(pos)
- -- handle timer
- if self.timer < self.patience then
- self.timer = self.timer + dtime
- else
- self.patience = 0
- self.timer = 0
- self.bob = false
- end
- else
- -- handle timer
- if self.timer < self.patience then
- self.timer = self.timer + dtime
- else
- -- waiting over, bob that bobber and play splash sound
- self.bob = true
- self.patience = 1.5 -- timeframe to catch fish after bob
- self.timer = 0
- self.object:set_velocity({x = 0, y = -1, z = 0})
- self.object:set_acceleration({x = 0, y = 3, z = 0})
- minetest.sound_play("default_water_footstep", {
- pos = pos, gain = 0.1}, true)
- end
- end
- else
- -- reset to original position after dive.
- if self.old_y and pos.y > self.old_y then
- self.object:set_velocity({x = 0, y = 0, z = 0})
- self.object:set_acceleration({x = 0, y = 0, z = 0})
- self.object:set_pos({x = pos.x, y = self.old_y, z = pos.z})
- --print("-- reset bob y pos")
- end
- -- remove if not in water and not bobbing
- if not self.bob then
- self.object:remove() ; --print("-- not in water")
- end
- end
- end -- if not self.cast
- end -- on_step
- })
- -- narrow item list depending on biome if applicable
- local find_item = function(list, pos)
- local item
- local items = {}
- local data= minetest.get_biome_data(pos)
- local biome = data and minetest.get_biome_name(data.biome) or ""
- for n = 1, #list do
- item = list[n]
- if type(item) == "string" then
- table.insert(items, item)
- elseif type(item) == "table" then
- if item[2] == "" or biome:find(item[2]) then
- table.insert(items, item[1])
- end
- end
- end
- --print("==biome: " .. biome, dump(items))
- if #items > 0 then
- return items[random(#items)]
- end
- return ""
- end
- -- fishing rod function that throws pre bob, places bob and catches fish when it moves
- local use_rod = function(itemstack, player, pointed_thing)
- local pos = player:get_pos()
- local objs = minetest.get_objects_inside_radius(pos, 15)
- local found = true
- local ent
- -- loop through entities and look for bobs
- for n = 1, #objs do
- ent = objs[n]:get_luaentity()
- if ent
- and ent.fisher
- and ent.name == "ethereal:bob_entity"
- and player:get_player_name() == ent.fisher then
- found = false
- if ent.bob == true then
- local item
- local r = random(100)
- if r < 86 then
- item = find_item(fish_items, pos)
- elseif r > 85 and r < 96 then
- item = find_item(junk_items, pos)
- else
- item = find_item(bonus_items, pos)
- end
- -- make sure item exists, if not replace with default item
- if not minetest.registered_items[item] then
- item = default_item
- end
- --print ("---caught", item, r)
- item = ItemStack(item)
- local inv = player:get_inventory()
- if inv:room_for_item("main", item) then
- inv:add_item("main", item)
- else
- minetest.add_item(pos, item)
- end
- end
- ent.object:remove()
- return itemstack
- end
- end
- -- loop through entities and look for bobs
- for n = 1, #objs do
- ent = objs[n]:get_luaentity()
- if ent
- and ent.fisher
- and ent.name == "ethereal:bob_entity"
- and player:get_player_name() == ent.fisher then
- found = false
- break
- end
- end
- if found == true then
- local playerpos = player:get_pos()
- local dir = player:get_look_dir()
- local pos = {x = playerpos.x, y = playerpos.y + 1.5, z = playerpos.z}
- minetest.sound_play("ethereal_casting_rod",
- {pos = pos, gain = 0.4, max_hear_distance = 16}, true)
- -- place actual bob
- local obj = minetest.add_entity(pos, "ethereal:bob_entity")
- obj:set_velocity({x = dir.x * 8, y = dir.y * 8, z = dir.z * 8})
- obj:set_acceleration({x = dir.x * -3, y = -9.8, z = dir.z * -3})
- obj:get_luaentity().fisher = player and player:get_player_name()
- end
- end
- -- scan area for bobs that belong to player and remove
- local remove_bob = function(player)
- local objs = minetest.get_objects_inside_radius(player:get_pos(), 15)
- local name = player:get_player_name()
- local ent
- for n = 1, #objs do
- ent = objs[n]:get_luaentity()
- if ent and ent.name == "ethereal:bob_entity" then
- -- only remove players own bob
- if ent.fisher and ent.fisher == name then
- ent.object:remove()
- end
- end
- end
- end
- -- remove bob if player signs off
- minetest.register_on_leaveplayer(function(player)
- remove_bob(player)
- end)
- -- remove bob if player dies
- minetest.register_on_dieplayer(function(player)
- remove_bob(player)
- end)
- -- fishing rod
- minetest.register_tool("ethereal:fishing_rod", {
- description = S("Fishing Rod (USE to cast and again when the time is right)"),
- groups = {tool = 1},
- inventory_image = "ethereal_fishing_rod.png",
- wield_image = "ethereal_fishing_rod.png^[transformFX",
- wield_scale = {x = 1.5, y = 1.5, z = 1},
- stack_max = 1,
- on_use = use_rod,
- sound = {breaks = "default_tool_breaks"}
- })
- minetest.register_craft({
- output = "ethereal:fishing_rod",
- recipe = {
- {"","","group:stick"},
- {"","group:stick","farming:string"},
- {"group:stick","","farming:string"}
- }
- })
- minetest.register_craft({
- type = "fuel",
- recipe = "ethereal:fishing_rod",
- burntime = 15
- })
- local fish = {
- {"Blue Fin", "bluefin", 2},
- {"Blue Ram", "blueram", 2},
- {"Catfish", "catfish", 2},
- {"Clownfish", "clownfish", 2},
- {"Pike", "pike", 2},
- {"Flathead", "flathead", 2},
- {"Plaice", "plaice", 2},
- {"Pufferfish", "pufferfish", -2},
- {"Coy", "coy", 2},
- {"Salmon", "salmon", 2},
- {"Cichlid", "cichlid", 2},
- {"Angler", "angler", 2},
- {"Jellyfish", "jellyfish", 0},
- {"Seahorse", "seahorse", 0},
- {"Piranha", "piranha", 2},
- {"Trout", "trout", 2}
- }
- for n = 1, #fish do
- local usage
- local groups
- if fish[n][3] > 0 then
- usage = minetest.item_eat(fish[n][3])
- groups = {food_fish_raw = 1, ethereal_fish = 1}
- end
- minetest.register_craftitem("ethereal:fish_" .. fish[n][2], {
- description = S(fish[n][1]),
- inventory_image = "ethereal_fish_" .. fish[n][2] .. ".png",
- on_use = usage,
- groups = groups
- })
- end
- -- cooked fish
- minetest.register_craftitem(":ethereal:fish_cooked", {
- description = S("Cooked Fish"),
- inventory_image = "ethereal_fish_cooked.png",
- wield_image = "ethereal_fish_cooked.png",
- groups = {food_fish = 1, flammable = 3},
- on_use = minetest.item_eat(5)
- })
- minetest.register_craft({
- type = "cooking",
- output = "ethereal:fish_cooked",
- recipe = "group:ethereal_fish",
- cooktime = 8
- })
- -- Sashimi (Thanks to Natalia Grosner for letting me use the sashimi image)
- minetest.register_craftitem("ethereal:sashimi", {
- description = S("Sashimi"),
- inventory_image = "ethereal_sashimi.png",
- wield_image = "ethereal_sashimi.png",
- on_use = minetest.item_eat(4)
- })
- minetest.register_craft({
- output = "ethereal:sashimi 2",
- recipe = {
- {"group:food_seaweed", "group:food_fish_raw", "group:food_seaweed"},
- }
- })
- -- Worm
- minetest.register_craftitem("ethereal:worm", {
- description = S("Worm"),
- inventory_image = "ethereal_worm.png",
- wield_image = "ethereal_worm.png"
- })
- minetest.register_craft({
- output = "ethereal:worm",
- recipe = {
- {"default:dirt", "default:dirt"}
- }
- })
- -- compatibility
- minetest.register_alias("ethereal:fish_raw", "ethereal:fish_cichlid")
- minetest.register_alias("ethereal:fishing_rod_baited", "ethereal:fishing_rod")
- minetest.register_alias("ethereal:fish_chichlid", "ethereal:fish_cichlid")
|