commit 474211ad671bd462d5cc522ea4f1c53ccc86b432 Author: MisterE123 <61124264+MisterE123@users.noreply.github.com> Date: Sat Mar 14 17:38:40 2020 -0400 added mod files diff --git a/README.md b/README.md new file mode 100644 index 0000000..b3a33d8 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# [Mod] Obsidian-Mese [obsidianmese] + +This MOD for Minetest adds more use for Mese and Obsidian. Add more variety of tools and blocks. +Further Description added by MisterE: +Tools added: +obsidianmese_sword- a good sword that can be crafted with obsidian and mese +obsidianmese_sword_engraved - a uncraftable sword that shoots shards that deal damage, or explode if they hit a node, removing 1 node and causing damage in a radius of 4. THIS IS SUPPOSED TO BE DROPPED BY DIFFICULT MOBS + +obsidianmese_pick - a good pickaxe that can be made with obsidian and mese +obsidianmese_pick_engraved - a good pickaxe that can be made with obsidian and diamond +obsidianmese_axe - cuts down all tree nodes above the one chopped +obsidianmese_hoe - can be used to hoe 4 dirt nodes at once +obsidianmese_shovel - a good shovel, or can be used to compact soil to form paths + +also adds: meseapple, 4 of which are craftable from a mese block and 4 apples. It restores full health when eaten. + +Original mod included: obsidianmese_boat, which was a boat for lava. It was removed by MisterE from this version. +Original mod included: balrog sword, this is still in the mod, but commented out. It failed testing by MisterE, and was left commented out. + + +## Boat -- removed from mod in this modification version + +* Originally by PilzAdam (MIT) +* Various Minetest developers and contributors (MIT) +* SaKeL (2018) + +### Textures + +* SaKeL (CC BY-SA 3.0) + +### Mesh model -- removed from mod in this modification version + +Boat mesh (`models/mcl_boats_boat.b3d`) created by 22i. +Source: https://github.com/22i/minecraft-voxel-blender-models + +License of boat model: +GNU GPLv3 diff --git a/api.lua b/api.lua new file mode 100644 index 0000000..9c0719f --- /dev/null +++ b/api.lua @@ -0,0 +1,531 @@ +obsidianmese = {} +-- save how many bullets owner fired +obsidianmese.fired_table = {} +local enable_particles = minetest.settings:get_bool("enable_particles") + +local function bound(x, minb, maxb) + if x < minb then + return minb + elseif x > maxb then + return maxb + else + return x + end +end + +--- Punch damage calculator. +-- By default, this just calculates damage in the vanilla way. Switch it out for something else to change the default damage mechanism for mobs. +-- @param ObjectRef player +-- @param ?ObjectRef puncher +-- @param number time_from_last_punch +-- @param table tool_capabilities +-- @param ?vector direction +-- @param ?Id attacker +-- @return number The calculated damage +-- @author raymoo +function obsidianmese.damage_calculator(player, puncher, tflp, caps, direction, attacker) + local a_groups = player:get_armor_groups() or {} + local full_punch_interval = caps.full_punch_interval or 1.4 + local time_prorate = bound(tflp / full_punch_interval, 0, 1) + + local damage = 0 + for group, damage_rating in pairs(caps.damage_groups or {}) do + local armor_rating = a_groups[group] or 0 + damage = damage + damage_rating * (armor_rating / 100) + end + + return math.floor(damage * time_prorate) +end + +-- particles +function obsidianmese.add_effects(pos) + if not enable_particles then return end + + return minetest.add_particlespawner({ + amount = 2, + time = 0, + minpos = {x=pos.x-1, y=pos.y+0.5, z=pos.z-1}, + maxpos = {x=pos.x+1, y=pos.y+1.5, z=pos.z+1}, + minvel = {x=-0.1, y=-0.1, z=-0.1}, + maxvel = {x=0.3, y=-0.3, z=0.3}, + minacc = vector.new(), + maxacc = vector.new(), + minexptime = 1, + maxexptime = 5, + minsize = .5, + maxsize = 1.5, + texture = "obsidianmese_chest_particle.png", + glow = 7 + }) +end + +-- check for player near by to activate particles +function obsidianmese.check_around_radius(pos) + local player_near = false + + for _,obj in ipairs(minetest.get_objects_inside_radius(pos, 16)) do + if obj:is_player() then + player_near = true + break + end + end + + return player_near +end + +-- check if within physical map limits (-30911 to 30927) +function obsidianmese.within_limits(pos, radius) + if (pos.x - radius) > -30913 + and (pos.x + radius) < 30928 + and (pos.y - radius) > -30913 + and (pos.y + radius) < 30928 + and (pos.z - radius) > -30913 + and (pos.z + radius) < 30928 then + return true -- within limits + end + + return false -- beyond limits +end + +-- remember how many bullets player fired i.e. {SaKeL: 1,...} +function obsidianmese.sync_fired_table(owner) + if obsidianmese.fired_table[owner] ~= nil then + if obsidianmese.fired_table[owner] < 0 then + obsidianmese.fired_table[owner] = 0 + else + obsidianmese.fired_table[owner] = obsidianmese.fired_table[owner] - 1 + end + -- print(minetest.serialize(fired_table)) + end +end + +function obsidianmese.fire_sword(itemstack, user, pointed_thing) + if not user:get_player_control().RMB then return end + + local speed = 8 + local pos = user:getpos() + local v = user:get_look_dir() + local player_name = user:get_player_name() + + if not obsidianmese.fired_table[player_name] or obsidianmese.fired_table[player_name] < 0 then + obsidianmese.fired_table[player_name] = 0 + end + + if obsidianmese.fired_table[player_name] >= 1 then + minetest.chat_send_player(player_name, "You can shoot 1 shot at the time!") + return itemstack + end + + obsidianmese.fired_table[player_name] = obsidianmese.fired_table[player_name] + 1 + + -- print(minetest.serialize(obsidianmese.fired_table)) + + -- adjust position from where the bullet will be fired based on the look direction + -- prevents hitting the node when looking/shooting down from the edge + pos.x = pos.x + v.x + pos.z = pos.z + v.z + if v.y > 0.4 or v.y < -0.4 then + pos.y = pos.y + v.y + else + pos.y = pos.y + 1 + end + + -- play shoot attack sound + minetest.sound_play("obsidianmese_throwing", { + pos = pos, + gain = 1.0, -- default + max_hear_distance = 10, + }) + + local obj = minetest.add_entity(pos, "obsidianmese:sword_bullet") + local ent = obj:get_luaentity() + + if ent then + ent._owner = player_name + + v.x = v.x * speed + v.y = v.y * speed + v.z = v.z * speed + + obj:setvelocity(v) + end + + -- wear tool + local wdef = itemstack:get_definition() + itemstack:add_wear(65535 / (150 - 1), pointed_thing.above) + -- Tool break sound + if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then + minetest.sound_play(wdef.sound.breaks, {pos = pointed_thing.above, gain = 0.5}) + end + return itemstack +end + +function obsidianmese.add_wear(itemstack, pos) + -- wear tool + local wdef = itemstack:get_definition() + itemstack:add_wear(65535 / (400 - 1)) + -- Tool break sound + if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then + minetest.sound_play(wdef.sound.breaks, {pos = pos, gain = 0.5}) + end + + return itemstack +end + +-- prevent pick axe engraved of placing item when clicken on one of the items from this list +local pick_engraved_place_blacklist = { + ["xdecor:itemframe"] = true +} + +function obsidianmese.pick_engraved_place(itemstack, placer, pointed_thing) + local idx = placer:get_wield_index() + 1 -- item to right of wielded tool + local inv = placer:get_inventory() + local stack = inv:get_stack("main", idx) -- stack to right of tool + local stack_name = stack:get_name() + local under = pointed_thing.under + local above = pointed_thing.above + local node_under = minetest.get_node(under) + local udef = {} + local temp_stack = "" + + -- handle nodes + if pointed_thing.type == "node" then + local pos = minetest.get_pointed_thing_position(pointed_thing) + local pointed_node = minetest.get_node(pos) + + -- check if we have to use default on_place first + if pick_engraved_place_blacklist[pointed_node.name] ~= nil then + return minetest.item_place(itemstack, placer, pointed_thing) + end + + if pointed_node ~= nil and stack_name ~= "" then + local stack_def = minetest.registered_nodes[stack_name] + local stack_name_split = string.split(stack_name, ":") + local stack_mod = stack_name_split[1] + + udef = minetest.registered_nodes[stack_name] + -- print(dump(udef)) + + -- not for farming - that should be part of a hoe + if stack_mod ~= "farming" or stack_mod ~= "farming_addons" then + if udef and udef.on_place then + temp_stack = udef.on_place(stack, placer, pointed_thing) or stack + inv:set_stack("main", idx, temp_stack) + + -- itemstack = obsidianmese.add_wear(itemstack) + + -- play sound + -- if udef.sounds then + -- if udef.sounds.place then + -- udef.sounds.place.to_player = placer:get_player_name() + -- minetest.sound_play(udef.sounds.place) + -- end + -- end + + return itemstack + elseif udef and udef.on_use then + temp_stack = udef.on_use(stack, placer, pointed_thing) or stack + inv:set_stack("main", idx, temp_stack) + + -- itemstack = obsidianmese.add_wear(itemstack) + return itemstack + end + end + + -- handle default torch placement + if stack_name == "default:torch" then + local wdir = minetest.dir_to_wallmounted(vector.subtract(under, above)) + local fakestack = stack + + if wdir == 0 then + fakestack:set_name("default:torch_ceiling") + elseif wdir == 1 then + fakestack:set_name("default:torch") + else + fakestack:set_name("default:torch_wall") + end + + temp_stack = minetest.item_place(fakestack, placer, pointed_thing, wdir) + + temp_stack:set_name("default:torch") + inv:set_stack("main", idx, temp_stack) + + -- itemstack = obsidianmese.add_wear(itemstack) + + -- play sound + -- if udef and udef.sounds then + -- if udef.sounds.place then + -- udef.sounds.place.to_player = placer:get_player_name() + -- minetest.sound_play(udef.sounds.place) + -- end + -- end + + return itemstack + end + end + -- if everything else fails use default on_place + stack = minetest.item_place(stack, placer, pointed_thing) + inv:set_stack("main", idx, stack) + + -- play sound + -- if udef and udef.sounds then + -- if udef.sounds.place then + -- udef.sounds.place.to_player = placer:get_player_name() + -- minetest.sound_play(udef.sounds.place) + -- end + -- end + + return itemstack + end +end + +function obsidianmese.shovel_place(itemstack, placer, pointed_thing) + local pt = pointed_thing + + -- check if pointing at a node + if not pt then + return + end + if pt.type ~= "node" then + return + end + + local under = minetest.get_node(pt.under) + local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z} + local above = minetest.get_node(p) + + -- return if any of the nodes is not registered + if not minetest.registered_nodes[under.name] then + return + end + if not minetest.registered_nodes[above.name] then + return + end + + -- check if the node above the pointed thing is air + if above.name ~= "air" then + return + end + + if minetest.is_protected(pt.under, placer:get_player_name()) then + minetest.record_protection_violation(pt.under, placer:get_player_name()) + return + end + + -- dirt path + if under.name == "default:dirt" and + under.name ~= "obsidianmese:path_dirt" then + minetest.set_node(pt.under, {name = "obsidianmese:path_dirt"}) + + -- grass path + elseif (under.name == "default:dirt_with_grass" or + under.name == "default:dirt_with_grass_footsteps" or + under.name == "default:dirt_with_dry_grass" or + under.name == "default:dirt_with_snow" or + under.name == "default:dirt_with_rainforest_litter") and + under.name ~= "obsidianmese:path_grass" then + minetest.set_node(pt.under, {name = "obsidianmese:path_grass"}) + + -- sand path + elseif under.name == "default:sand" and + under.name ~= "obsidianmese:path_sand" then + minetest.set_node(pt.under, {name = "obsidianmese:path_sand"}) + + -- desert sand path + elseif under.name == "default:desert_sand" and + under.name ~= "obsidianmese:path_desert_sand" then + minetest.set_node(pt.under, {name = "obsidianmese:path_desert_sand"}) + + -- silver sand path + elseif under.name == "default:silver_sand" and + under.name ~= "obsidianmese:path_silver_sand" then + minetest.set_node(pt.under, {name = "obsidianmese:path_silver_sand"}) + + -- snow path + elseif under.name == "default:snowblock" and + under.name ~= "obsidianmese:path_snowblock" then + minetest.set_node(pt.under, {name = "obsidianmese:path_snowblock"}) + + else + return + end + + -- play sound + minetest.sound_play("default_dig_crumbly", { + pos = pt.under, + gain = 0.5 + }) + -- add wear + itemstack = obsidianmese.add_wear(itemstack) + return itemstack +end + +-- axe dig upwards +function obsidianmese.dig_up(pos, node, digger) + if not digger then + return + end + + local wielditemname = digger:get_wielded_item():get_name() + local whitelist = { + ["obsidianmese:axe"] = true, + ["obsidianmese:enchanted_axe_durable"] = true, + ["obsidianmese:enchanted_axe_fast"] = true + } + + if not whitelist[wielditemname] then + return + end + + local np = {x = pos.x, y = pos.y + 1, z = pos.z} + local nn = minetest.get_node(np) + + if nn.name == node.name then + local branches_pos = minetest.find_nodes_in_area( + {x = np.x - 1, y = np.y, z = np.z - 1}, + {x = np.x + 1, y = np.y + 1, z = np.z + 1}, + node.name + ) + + minetest.node_dig(np, nn, digger) + + -- try to find a node texture + local def = minetest.registered_nodes[nn.name] + local texture = "default_dirt.png" + + if def then + if def.tiles then + if #def.tiles > 0 then + if type(def.tiles[1]) == "string" then + texture = def.tiles[1] + end + end + end + end + + -- add particles only when not too far + minetest.add_particlespawner({ + amount = math.random(1, 3), + time = 0.5, + minpos = {x=np.x-0.7, y=np.y, z=np.z-0.7}, + maxpos = {x=np.x+0.7, y=np.y+0.75, z=np.z+0.7}, + minvel = {x = -0.5, y = -4, z = -0.5}, + maxvel = {x = 0.5, y = -2, z = 0.5}, + minacc = {x = -0.5, y = -4, z = -0.5}, + maxacc = {x = 0.5, y = -2, z = 0.5}, + minexptime = 0.5, + maxexptime = 1, + minsize = 0.5, + maxsize = 2, + collisiondetection = true, + texture = texture + }) + + if #branches_pos > 0 then + for i = 1, #branches_pos do + -- prevent infinite loop when node protected + if minetest.is_protected(branches_pos[i], digger:get_player_name()) then + break + end + + obsidianmese.dig_up({x = branches_pos[i].x, y = branches_pos[i].y - 1, z = branches_pos[i].z}, node, digger) + end + end + end +end + +function obsidianmese.register_capitator() + local trees = { + "default:tree", + "default:jungletree", + "default:pine_tree", + "default:acacia_tree", + "default:aspen_tree" + } + + for i = 1, #trees do + local ndef = minetest.registered_nodes[trees[i]] + local prev_after_dig = ndef.after_dig_node + local func = function(pos, node, metadata, digger) + obsidianmese.dig_up(pos, node, digger) + end + + if prev_after_dig then + func = function(pos, node, metadata, digger) + prev_after_dig(pos, node, metadata, digger) + obsidianmese.dig_up(pos, node, digger) + end + end + minetest.override_item(trees[i], {after_dig_node = func}) + end +end + +-- Taken from WorldEdit +-- Determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1) +function obsidianmese.player_axis(player) + local dir = player:get_look_dir() + local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z) + if x > y then + if x > z then + return "x", dir.x > 0 and 1 or -1 + end + elseif y > z then + return "y", dir.y > 0 and 1 or -1 + end + return "z", dir.z > 0 and 1 or -1 +end + +function obsidianmese.hoe_on_use(itemstack, user, pointed_thing) + local pt = pointed_thing + -- check if pointing at a node + if not pt then + return + end + if pt.type ~= "node" then + return + end + + local under = minetest.get_node(pt.under) + local p = {x=pt.under.x, y=pt.under.y+1, z=pt.under.z} + local above = minetest.get_node(p) + + -- return if any of the nodes is not registered + if not minetest.registered_nodes[under.name] then + return + end + if not minetest.registered_nodes[above.name] then + return + end + + -- check if the node above the pointed thing is air + if above.name ~= "air" then + return + end + + -- check if pointing at soil + if minetest.get_item_group(under.name, "soil") ~= 1 then + return + end + + -- check if (wet) soil defined + local regN = minetest.registered_nodes + if regN[under.name].soil == nil or regN[under.name].soil.wet == nil or regN[under.name].soil.dry == nil then + return + end + + if minetest.is_protected(pt.under, user:get_player_name()) then + minetest.record_protection_violation(pt.under, user:get_player_name()) + return + end + if minetest.is_protected(pt.above, user:get_player_name()) then + minetest.record_protection_violation(pt.above, user:get_player_name()) + return + end + + -- turn the node into soil and play sound + minetest.set_node(pt.under, {name = regN[under.name].soil.dry}) + minetest.sound_play("default_dig_crumbly", { + pos = pt.under, + gain = 0.5, + }) +end diff --git a/crafting.lua b/crafting.lua new file mode 100644 index 0000000..846f288 --- /dev/null +++ b/crafting.lua @@ -0,0 +1,90 @@ +-- +-- Craft Items +-- + +-- mese apple +minetest.register_craftitem("obsidianmese:mese_apple", { + description = "Mese apple [restores full health]", + inventory_image = "obsidianmese_apple.png", + on_use = function(itemstack, user, pointed_thing) + + minetest.sound_play("obsidianmese_apple_eat", { + pos = user:getpos(), + max_hear_distance = 32, + gain = 0.5, + }) + + user:set_hp(20) + itemstack:take_item() + return itemstack + end +}) + +-- +-- Crafting +-- no craft for engraved sword, that is rare item obtained only by drops +-- + + +minetest.register_craft({ + output = "obsidianmese:sword", + recipe = { + {"", "default:mese_crystal", ""}, + {"default:obsidian_shard", "default:mese_crystal", "default:obsidian_shard"}, + {"", "default:obsidian_shard", ""}, + } +}) + +minetest.register_craft({ + output = "obsidianmese:pick", + recipe = { + {"default:mese_crystal", "default:mese_crystal", "default:mese_crystal"}, + {"", "default:obsidian_shard", ""}, + {"", "default:obsidian_shard", ""}, + } +}) + +minetest.register_craft({ + output = "obsidianmese:shovel", + recipe = { + {"default:mese_crystal"}, + {"default:obsidian_shard"}, + {"default:obsidian_shard"}, + } +}) +-- a tree capitator axe is powerful, so I changed one of the required mese crystals into a mese block +minetest.register_craft({ + output = "obsidianmese:axe", + recipe = { + {"default:mese_crystal", "default:mese"}, + {"default:mese_crystal", "default:obsidian_shard"}, + {"", "default:obsidian_shard"}, + } +}) + + minetest.register_craft({ + output = "obsidianmese:hoe", + recipe = { + {"default:mese_crystal", "default:mese_crystal", ""}, + {"", "default:obsidian_shard", ""}, + {"", "default:obsidian_shard", ""}, + } + }) + +minetest.register_craft({ + output = "obsidianmese:pick_engraved", + recipe = { + {"default:diamond", "default:diamond", "default:diamond"}, + {"", "default:obsidian_shard", ""}, + {"", "default:obsidian_shard", ""}, + } +}) + +minetest.register_craft({ + output = "obsidianmese:mese_apple 4", + recipe = { + {"", "default:apple", ""}, + {"default:apple","default:mese", "default:apple"}, + {"", "default:apple", ""}, + } +}) diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..845d8d2 --- /dev/null +++ b/depends.txt @@ -0,0 +1,2 @@ +default +tnt diff --git a/description.txt b/description.txt new file mode 100644 index 0000000..460a6da --- /dev/null +++ b/description.txt @@ -0,0 +1 @@ +This MOD for Minetest adds obsidian and mese tools and items. diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..3d6cd66 --- /dev/null +++ b/init.lua @@ -0,0 +1,14 @@ +-- +-- Init +-- + +dofile(minetest.get_modpath("obsidianmese").."/api.lua") +dofile(minetest.get_modpath("obsidianmese").."/tools.lua") +dofile(minetest.get_modpath("obsidianmese").."/nodes.lua") + + +dofile(minetest.get_modpath("obsidianmese").."/crafting.lua") + +obsidianmese.register_capitator() + +print("[Mod] ObsidianMese Loaded.") diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..a7451b9 --- /dev/null +++ b/license.txt @@ -0,0 +1,64 @@ +License of source code +---------------------- + +The MIT License (MIT) +Copyright (C) 2012-2016 PilzAdam +Copyright (C) 2012-2016 Various Minetest developers and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +For more details: +https://opensource.org/licenses/MIT + +note: this minetest mod has been modified from the version found on minetest_gamers repositories. Latest Modifications are by MisterE + +Licenses of media (textures and model) +-------------------------------------- + +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) +Copyright (C) 2012-2016 Zeg9 +Copyright (C) 2012-2016 thetoon +Copyright (C) 2012-2016 PavelS(SokolovPavel) +Copyright (C) 2016 sofar (sofar@foo-projects.org) + +You are free to: +Share — copy and redistribute the material in any medium or format. +Adapt — remix, transform, and build upon the material for any purpose, even commercially. +The licensor cannot revoke these freedoms as long as you follow the license terms. + +Under the following terms: + +Attribution — You must give appropriate credit, provide a link to the license, and +indicate if changes were made. You may do so in any reasonable manner, but not in any way +that suggests the licensor endorses you or your use. + +ShareAlike — If you remix, transform, or build upon the material, you must distribute +your contributions under the same license as the original. + +No additional restrictions — You may not apply legal terms or technological measures that +legally restrict others from doing anything the license permits. + +Notices: + +You do not have to comply with the license for elements of the material in the public +domain or where your use is permitted by an applicable exception or limitation. +No warranties are given. The license may not give you all of the permissions necessary +for your intended use. For example, other rights such as publicity, privacy, or moral +rights may limit how you use the material. + +For more details: +http://creativecommons.org/licenses/by-sa/3.0/ diff --git a/mod.conf b/mod.conf new file mode 100644 index 0000000..1faa8fd --- /dev/null +++ b/mod.conf @@ -0,0 +1,3 @@ +name = obsidianmese +description = This MOD for Minetest adds obsidian and mese tools and items. +depends = default, tnt diff --git a/nodes.lua b/nodes.lua new file mode 100644 index 0000000..5deeb4e --- /dev/null +++ b/nodes.lua @@ -0,0 +1,155 @@ +-- +-- Nodes +-- + +-- dirt path +minetest.register_node("obsidianmese:path_dirt", { + description = "Dirt Path", + drawtype = "nodebox", + tiles = {"obsidianmese_dirt_path_top.png", "obsidianmese_dirt_path_top.png", "obsidianmese_dirt_path_side.png"}, + is_ground_content = false, + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + drop = "default:dirt", + is_ground_content = false, + groups = {crumbly = 3, not_in_creative_inventory = 1}, + sounds = default.node_sound_dirt_defaults(), +}) + +-- grass path +minetest.register_node("obsidianmese:path_grass", { + description = "Grass Path", + drawtype = "nodebox", + tiles = {"obsidianmese_grass_path_top.png", "obsidianmese_dirt_path_top.png", "obsidianmese_dirt_path_side.png"}, + is_ground_content = false, + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + drop = "default:dirt", + is_ground_content = false, + groups = {crumbly = 3, not_in_creative_inventory = 1}, + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_grass_footstep", gain = 0.25}, + }), +}) + +-- sand path +minetest.register_node("obsidianmese:path_sand", { + description = "Sand Path", + drawtype = "nodebox", + tiles = {"obsidianmese_sand_path_top.png", "obsidianmese_sand_path_top.png", "obsidianmese_sand_path_side.png"}, + is_ground_content = false, + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + drop = "default:sand", + groups = {crumbly = 3, falling_node = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +-- desert sand path +minetest.register_node("obsidianmese:path_desert_sand", { + description = "Desert Sand Path", + drawtype = "nodebox", + tiles = {"obsidianmese_desert_sand_path_top.png", "obsidianmese_desert_sand_path_top.png", "obsidianmese_desert_sand_path_side.png"}, + is_ground_content = false, + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + drop = "default:desert_sand", + groups = {crumbly = 3, falling_node = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +-- silver sand +minetest.register_node("obsidianmese:path_silver_sand", { + description = "Silver Sand Path", + drawtype = "nodebox", + tiles = {"obsidianmese_silver_sand_path_top.png", "obsidianmese_silver_sand_path_top.png", "obsidianmese_silver_sand_path_side.png"}, + is_ground_content = false, + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + drop = "default:silver_sand", + groups = {crumbly = 3, falling_node = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_sand_defaults(), +}) + +-- snow path +minetest.register_node("obsidianmese:path_snowblock", { + description = "Snow Path", + drawtype = "nodebox", + tiles = {"obsidianmese_snow_path_top.png", "obsidianmese_snow_path_top.png", "obsidianmese_snow_path_side.png"}, + is_ground_content = false, + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + collision_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + selection_box = { + type = "fixed", + fixed = {-1/2, -1/2, -1/2, 1/2, 1/2-1/16, 1/2}, + }, + drop = "default:snowblock", + groups = {crumbly = 3, puts_out_fire = 1, cools_lava = 1, snowy = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_dirt_defaults({ + footstep = {name = "default_snow_footstep", gain = 0.15}, + dug = {name = "default_snow_footstep", gain = 0.2}, + dig = {name = "default_snow_footstep", gain = 0.2} + }), +}) diff --git a/sounds/obsidianmese_apple_eat.1.ogg b/sounds/obsidianmese_apple_eat.1.ogg new file mode 100644 index 0000000..7696eee Binary files /dev/null and b/sounds/obsidianmese_apple_eat.1.ogg differ diff --git a/sounds/obsidianmese_apple_eat.2.ogg b/sounds/obsidianmese_apple_eat.2.ogg new file mode 100644 index 0000000..d83847d Binary files /dev/null and b/sounds/obsidianmese_apple_eat.2.ogg differ diff --git a/sounds/obsidianmese_chest_close.ogg b/sounds/obsidianmese_chest_close.ogg new file mode 100644 index 0000000..65af7ea Binary files /dev/null and b/sounds/obsidianmese_chest_close.ogg differ diff --git a/sounds/obsidianmese_chest_open.ogg b/sounds/obsidianmese_chest_open.ogg new file mode 100644 index 0000000..9842604 Binary files /dev/null and b/sounds/obsidianmese_chest_open.ogg differ diff --git a/sounds/obsidianmese_throwing.ogg b/sounds/obsidianmese_throwing.ogg new file mode 100644 index 0000000..411598c Binary files /dev/null and b/sounds/obsidianmese_throwing.ogg differ diff --git a/textures/obsidianmese_apple.png b/textures/obsidianmese_apple.png new file mode 100644 index 0000000..374b7d0 Binary files /dev/null and b/textures/obsidianmese_apple.png differ diff --git a/textures/obsidianmese_axe.png b/textures/obsidianmese_axe.png new file mode 100644 index 0000000..0f721dc Binary files /dev/null and b/textures/obsidianmese_axe.png differ diff --git a/textures/obsidianmese_desert_sand_path_side.png b/textures/obsidianmese_desert_sand_path_side.png new file mode 100644 index 0000000..7b9c47a Binary files /dev/null and b/textures/obsidianmese_desert_sand_path_side.png differ diff --git a/textures/obsidianmese_desert_sand_path_top.png b/textures/obsidianmese_desert_sand_path_top.png new file mode 100644 index 0000000..5c18713 Binary files /dev/null and b/textures/obsidianmese_desert_sand_path_top.png differ diff --git a/textures/obsidianmese_dirt_path_side.png b/textures/obsidianmese_dirt_path_side.png new file mode 100644 index 0000000..739e158 Binary files /dev/null and b/textures/obsidianmese_dirt_path_side.png differ diff --git a/textures/obsidianmese_dirt_path_top.png b/textures/obsidianmese_dirt_path_top.png new file mode 100644 index 0000000..674863e Binary files /dev/null and b/textures/obsidianmese_dirt_path_top.png differ diff --git a/textures/obsidianmese_grass_path_top.png b/textures/obsidianmese_grass_path_top.png new file mode 100644 index 0000000..a06d903 Binary files /dev/null and b/textures/obsidianmese_grass_path_top.png differ diff --git a/textures/obsidianmese_hoe.png b/textures/obsidianmese_hoe.png new file mode 100644 index 0000000..1bf2055 Binary files /dev/null and b/textures/obsidianmese_hoe.png differ diff --git a/textures/obsidianmese_pick.png b/textures/obsidianmese_pick.png new file mode 100644 index 0000000..5e37b47 Binary files /dev/null and b/textures/obsidianmese_pick.png differ diff --git a/textures/obsidianmese_pick_engraved.png b/textures/obsidianmese_pick_engraved.png new file mode 100644 index 0000000..6ce7572 Binary files /dev/null and b/textures/obsidianmese_pick_engraved.png differ diff --git a/textures/obsidianmese_sand_path_side.png b/textures/obsidianmese_sand_path_side.png new file mode 100644 index 0000000..215b713 Binary files /dev/null and b/textures/obsidianmese_sand_path_side.png differ diff --git a/textures/obsidianmese_sand_path_top.png b/textures/obsidianmese_sand_path_top.png new file mode 100644 index 0000000..493b674 Binary files /dev/null and b/textures/obsidianmese_sand_path_top.png differ diff --git a/textures/obsidianmese_shard.png b/textures/obsidianmese_shard.png new file mode 100644 index 0000000..a988d8c Binary files /dev/null and b/textures/obsidianmese_shard.png differ diff --git a/textures/obsidianmese_shovel.png b/textures/obsidianmese_shovel.png new file mode 100644 index 0000000..9d2b50c Binary files /dev/null and b/textures/obsidianmese_shovel.png differ diff --git a/textures/obsidianmese_silver_sand_path_side.png b/textures/obsidianmese_silver_sand_path_side.png new file mode 100644 index 0000000..fa50366 Binary files /dev/null and b/textures/obsidianmese_silver_sand_path_side.png differ diff --git a/textures/obsidianmese_silver_sand_path_top.png b/textures/obsidianmese_silver_sand_path_top.png new file mode 100644 index 0000000..3598255 Binary files /dev/null and b/textures/obsidianmese_silver_sand_path_top.png differ diff --git a/textures/obsidianmese_snow_path_side.png b/textures/obsidianmese_snow_path_side.png new file mode 100644 index 0000000..5393a56 Binary files /dev/null and b/textures/obsidianmese_snow_path_side.png differ diff --git a/textures/obsidianmese_snow_path_top.png b/textures/obsidianmese_snow_path_top.png new file mode 100644 index 0000000..fc63fe6 Binary files /dev/null and b/textures/obsidianmese_snow_path_top.png differ diff --git a/textures/obsidianmese_sword.png b/textures/obsidianmese_sword.png new file mode 100644 index 0000000..2fab018 Binary files /dev/null and b/textures/obsidianmese_sword.png differ diff --git a/textures/obsidianmese_sword_balrog_boss.png b/textures/obsidianmese_sword_balrog_boss.png new file mode 100644 index 0000000..8fc9951 Binary files /dev/null and b/textures/obsidianmese_sword_balrog_boss.png differ diff --git a/textures/obsidianmese_sword_diamond_engraved.png b/textures/obsidianmese_sword_diamond_engraved.png new file mode 100644 index 0000000..edfaa2e Binary files /dev/null and b/textures/obsidianmese_sword_diamond_engraved.png differ diff --git a/tools.lua b/tools.lua new file mode 100644 index 0000000..5aaee29 --- /dev/null +++ b/tools.lua @@ -0,0 +1,409 @@ +-- +-- Tools +-- + +-- sword +minetest.register_tool("obsidianmese:sword", { + description = "Obsidian Mese Sword", + inventory_image = "obsidianmese_sword.png", + wield_scale = {x=1.5, y=2, z=1}, + tool_capabilities = { + full_punch_interval = 0.45, + max_drop_level=1, + groupcaps={ + fleshy={times={[1]=2.00, [2]=0.65, [3]=0.25}, uses=400, maxlevel=3}, + snappy={times={[1]=1.90, [2]=0.70, [3]=0.25}, uses=350, maxlevel=3}, + choppy={times={[3]=0.65}, uses=300, maxlevel=0} + }, + damage_groups = {fleshy=8}, + }, + sound = {breaks = "default_tool_breaks"} +}) + +-- boss sword - balrog - left commented out as I found it, because it does not seem to work, debugging required. +--[[ minetest.register_tool("obsidianmese:sword_balrog_boss", { + description = "Boss Sword", + inventory_image = "obsidianmese_sword_balrog_boss.png", + wield_scale = {x=2.2, y=2.7, z=1.7}, + tool_capabilities = { + full_punch_interval = 2, + max_drop_level=1, + groupcaps={ + snappy={times={[1]=1.90, [2]=0.90, [3]=0.30}, uses=20, maxlevel=3}, + } + }, + damage_groups = {fleshy=10}, + sound = {breaks = "default_tool_breaks"}, + on_use = function(itemstack, user, pointed_thing) + print("on_use") + print(dump(pointed_thing)) + end, + after_use = function(itemstack, user, node, digparams) + print("after_use") + itemstack:add_wear(digparams.wear) + return itemstack + end +}) ]]-- + +-- sword engraved - bullet entity +minetest.register_entity("obsidianmese:sword_bullet", { + physical = false, + visual = "sprite", + visual_size = { x = 1, y = 1 }, + textures = { "obsidianmese_shard.png" }, + collisionbox = {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25}, + _lifetime = 9, -- seconds before removing + _timer = 0, -- initial value + _owner = "unknown", -- initial value + _trigger_sd = 0, + + on_activate = function(self, staticdata, dtime_s) + local table = minetest.deserialize(staticdata) + -- check - initial values are empty + if table then + self._owner = table._owner + self._timer = table._timer + end + self.object:set_armor_groups({ immortal = 1 }) + end, + + -- should return a string that will be passed to `on_activate` when the object is instantiated the next time + get_staticdata = function(self) + self._trigger_sd = self._trigger_sd + 1 + + -- staticdata are triggered before object appears and before it hides from the World, so remove it before it hides + if self._trigger_sd % 2 == 0 then + self.object:remove() + obsidianmese.sync_fired_table(self._owner) + end + + -- insurance - makes sure staticdata are updated when objects activates again (because somehow wasn't removed yet) + local table = { + _owner = self._owner, + _timer = self._timer + } + return minetest.serialize(table) + end, + + -- when the entity gets punched + on_punch = function (self, puncher, time_from_last_punch, tool_capabilities, dir) + local full_punch_interval = tool_capabilities.full_punch_interval or 1 + + -- only on full punch + if time_from_last_punch < full_punch_interval then return end + + local v = math.random(1, 8) + local velocity = dir + + velocity.x = velocity.x * v + velocity.y = velocity.y * v + velocity.z = velocity.z * v + self.object:setvelocity(velocity) + end, + + on_step = function(self, dtime) + local pos = self.object:getpos() + local node = minetest.get_node_or_nil(pos) + + -- print("self._owner: ", self._owner) + -- print("self._timer: ", self._timer) + + self._timer = self._timer + dtime + if self._timer > self._lifetime or + not obsidianmese.within_limits(pos, 0) then + self.object:remove() + obsidianmese.sync_fired_table(self._owner) + return + end + + -- hit node + if node + and minetest.registered_nodes[node.name] + and minetest.registered_nodes[node.name].walkable then + self.object:remove() + obsidianmese.sync_fired_table(self._owner) + + -- dont damage anything if area protected or next to water + if minetest.find_node_near(pos, 1, {"group:water"}) + or minetest.is_protected(pos, "") then + return + end +-- this is where the shot shard can explode when it hets a node. It was commented out, +-- I uncommented it, but changed the explosion radius to 1, and the damage to 4. That should make it non-griefy. + tnt.boom(pos, { + radius = 1, + damage_radius = 4, + ignore_protection = false, + ignore_on_blast = false, + disable_drops = false + }) + return + end + + -- hit player or mob + for k, obj in ipairs(minetest.get_objects_inside_radius(pos, 1)) do + if obj:is_player() then + -- pvp block + if minetest.global_exists("pvp_block") then + local dmg = obsidianmese.damage_calculator( + obj, + minetest.get_player_by_name(self._owner), + 1.0, + { + full_punch_interval = 1.0, + damage_groups = {fleshy = 8}, + }, + nil, + nil + ) + + pvp_block.register_on_punchplayer( + obj, -- player + minetest.get_player_by_name(self._owner), --hitter + 1.0, -- time_from_last_punch + { + full_punch_interval = 1.0, + damage_groups = {fleshy = 8}, + }, -- tool_capabilities + nil, -- dir + dmg -- damage i.e. {fleshy = 8} + ) + end + + -- punch player + obj:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = 8}, + }, nil) + + self.object:remove() + obsidianmese.sync_fired_table(self._owner) + + break + -- punch entity + elseif not obj:is_player() and + obj:get_luaentity() and + obj:get_luaentity().name ~= "__builtin:item" then + local entity = obj:get_luaentity() + + if entity.name ~= self.object:get_luaentity().name then + obj:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = 8}, + }, nil) + + self.object:remove() + obsidianmese.sync_fired_table(self._owner) + break + end + end + end + end +}) + +-- sword engraved +minetest.register_tool("obsidianmese:sword_engraved", { + description = "Obsidian Mese Sword Engraved - right click shoot 1 shot", + inventory_image = "obsidianmese_sword_diamond_engraved.png", + wield_scale = {x=1.5, y=2, z=1}, + tool_capabilities = { + full_punch_interval = 0.6, + max_drop_level=1, + groupcaps={ + snappy={times={[1]=1.90, [2]=0.90, [3]=0.30}, uses=300, maxlevel=3}, + }, + damage_groups = {fleshy=8}, + }, + sound = {breaks = "default_tool_breaks"}, + on_secondary_use = obsidianmese.fire_sword +}) + +-- pick axe +minetest.register_tool("obsidianmese:pick", { + description = "Obsidian Mese Pickaxe", + inventory_image = "obsidianmese_pick.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=3, + groupcaps={ + cracky={times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=250, maxlevel=3}, + crumbly={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=350, maxlevel=3}, + snappy={times={[1]=2.0, [2]=1.0, [3]=0.5}, uses=300, maxlevel=3} + }, + damage_groups = {fleshy=5}, + }, + sound = {breaks = "default_tool_breaks"}, +}) + +-- pick axe engraved +minetest.register_tool("obsidianmese:pick_engraved", { + description = "Obsidian Mese Pickaxe Engraved - right click to place item next to the pickaxe in your inventory slot", + inventory_image = "obsidianmese_pick_engraved.png", + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=3, + groupcaps={ + cracky={times={[1]=2.0, [2]=1.0, [3]=0.50}, uses=200, maxlevel=3} + }, + damage_groups = {fleshy=5}, + }, + sound = {breaks = "default_tool_breaks"}, + on_place = obsidianmese.pick_engraved_place +}) + +-- shovel +minetest.register_tool("obsidianmese:shovel", { + description = "Obsidian Mese Shovel - right click (secondary click) for creating a path", + inventory_image = "obsidianmese_shovel.png", + wield_image = "obsidianmese_shovel.png^[transformR90", + wield_scale = {x=1.5, y=1.5, z=1.5}, + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=1, + groupcaps={ + crumbly = {times={[1]=1.10, [2]=0.50, [3]=0.30}, uses=50, maxlevel=3}, + }, + damage_groups = {fleshy=4}, + }, + sound = {breaks = "default_tool_breaks"}, + on_place = obsidianmese.shovel_place +}) + +-- axe +minetest.register_tool("obsidianmese:axe", { + description = "Obsidian Mese Axe - Tree Capitator", + inventory_image = "obsidianmese_axe.png", + wield_scale = {x=1.5, y=2, z=1}, + tool_capabilities = { + full_punch_interval = 0.9, + max_drop_level=1, + groupcaps={ + choppy={times={[1]=2.10, [2]=0.90, [3]=0.50}, uses=30, maxlevel=3}, + }, + damage_groups = {fleshy=7}, + }, + sound = {breaks = "default_tool_breaks"}, +}) + +--hoe + minetest.register_tool("obsidianmese:hoe", { + description = "Obsidian Mese Hoe", + inventory_image = "obsidianmese_hoe.png", + sound = {breaks = "default_tool_breaks"}, + on_use = function(itemstack, user, pointed_thing) + local axis, dir = obsidianmese.player_axis(user) + local pt = pointed_thing + local under = pt.under + if not under then return end + local wdef = itemstack:get_definition() + local uses = 500 + + for i = 0, 4 do + + if axis == "x" then + pt.under = { + x = under.x + (i * dir), + y = under.y, + z = under.z + } + + elseif axis == "z" then + pt.under = { + x = under.x, + y = under.y, + z = under.z + (i * dir) + } + end + + -- print(obsidianmese.player_axis(user)) + + obsidianmese.hoe_on_use(itemstack, user, pointed_thing) + + if not (creative and creative.is_enabled_for + and creative.is_enabled_for(user:get_player_name())) then + -- wear tool + itemstack:add_wear(65535/(uses-1)) + -- tool break sound + if itemstack:get_count() == 0 and wdef.sound and wdef.sound.breaks then + minetest.sound_play(wdef.sound.breaks, {pos = pt.above, gain = 0.5}) + end + end + end + return itemstack + end, + on_place = function(itemstack, placer, pointed_thing) + local idx = placer:get_wield_index() + 1 -- item to right of wielded tool + local inv = placer:get_inventory() + local stack = inv:get_stack("main", idx) -- stack to right of tool + local stack_name = stack:get_name() + local axis, dir = obsidianmese.player_axis(placer) + local pt = pointed_thing + local above = pt.above + local under = pt.under + if not above or not under then return end + local udef = {} + local temp_stack = {} + + if pt.type == "node" then + local pos = minetest.get_pointed_thing_position(pt) + local pointed_node = minetest.get_node(pos) + + if pointed_node ~= nil and stack_name ~= "" then + local stack_name_split = string.split(stack_name, ":") + local stack_mod = stack_name_split[1] + + udef = minetest.registered_nodes[stack_name] + + -- handle default farming and farming_addons placement + if stack_mod == "farming" or stack_mod == "farming_addons" then + for i = 0, 4 do + print("farming.place_seed") + + if axis == "x" then + pt.above = { + x = above.x + (i * dir), + y = above.y, + z = above.z + } + pt.under = { + x = under.x + (i * dir), + y = under.y, + z = under.z + } + + elseif axis == "z" then + pt.above = { + x = above.x, + y = above.y, + z = above.z + (i * dir) + } + pt.under = { + x = under.x, + y = under.y, + z = under.z + (i * dir) + } + end + + udef = minetest.registered_nodes[stack_name] + + if udef and udef.on_place then + temp_stack = udef.on_place(stack, placer, pt) or stack + elseif udef and udef.on_use then + temp_stack = udef.on_use(stack, placer, pt) or stack + end + + -- temp_stack = obsidianmese.place_seed(stack, placer, pt, stack_name) + inv:set_stack("main", idx, temp_stack) + + -- itemstack = obsidianmese.add_wear(itemstack) + -- return itemstack + end + end + end + -- if everything else fails use default on_place + -- stack = minetest.item_place(stack, placer, pt) + -- inv:set_stack("main", idx, stack) + return itemstack + end + end, + })