diff --git a/mods/CORE/mcl_damage/init.lua b/mods/CORE/mcl_damage/init.lua index 262b0cf55..740ac2b65 100644 --- a/mods/CORE/mcl_damage/init.lua +++ b/mods/CORE/mcl_damage/init.lua @@ -161,9 +161,9 @@ minetest.register_on_dieplayer(function(player, mt_reason) if mt_reason.approved then mcl_damage.run_death_callbacks(player, mcl_damage.from_mt(mt_reason)) end + minetest.log("action","Player "..player:get_player_name().." died at "..minetest.pos_to_string(vector.round(player:get_pos()))) end) minetest.register_on_mods_loaded(function() table.sort(mcl_damage.modifiers, function(a, b) return a.priority < b.priority end) end) - diff --git a/mods/ENTITIES/mcl_item_entity/init.lua b/mods/ENTITIES/mcl_item_entity/init.lua index ccf1d2dca..e8076606e 100644 --- a/mods/ENTITIES/mcl_item_entity/init.lua +++ b/mods/ENTITIES/mcl_item_entity/init.lua @@ -847,15 +847,16 @@ minetest.register_entity(":__builtin:item", { elseif self._flowing == true and not is_in_water and not is_floating then -- Disable flowing physics if not on/in flowing liquid self._flowing = false - disable_physics(self.object, self, true) + enable_physics(self.object, self, true) return end -- If node is not registered or node is walkably solid and resting on nodebox local nn = minetest.get_node({x=p.x, y=p.y-0.5, z=p.z}).name + local def = minetest.registered_nodes[nn] local v = self.object:get_velocity() - local is_on_floor = (minetest.registered_nodes[nn].walkable - and not minetest.registered_nodes[nn].groups.slippery and v.y == 0) + local is_on_floor = def and (def.walkable + and not def.groups.slippery and v.y == 0) if not minetest.registered_nodes[nn] or is_floating or is_on_floor then diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 8cbe9b8ca..8f49e71d4 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -213,11 +213,11 @@ end local collision = function(self) local pos = self.object:get_pos() + if not pos then return {0,0} end local vel = self.object:get_velocity() local x = 0 local z = 0 local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 - for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do local ent = object:get_luaentity() @@ -254,12 +254,14 @@ local set_velocity = function(self, v) end local yaw = (self.object:get_yaw() or 0) + self.rotate - - self.object:set_velocity({ - x = (sin(yaw) * -v) + c_x, - y = self.object:get_velocity().y, - z = (cos(yaw) * v) + c_y, - }) + local vv = self.object:get_velocity() + if vv then + self.object:set_velocity({ + x = (sin(yaw) * -v) + c_x, + y = vv.y, + z = (cos(yaw) * v) + c_y, + }) + end end @@ -407,15 +409,15 @@ local set_animation = function(self, anim, fixed_frame) if flight_check(self) and self.fly and anim == "walk" then anim = "fly" end - self.animation.current = self.animation.current or "" + self._current_animation = self._current_animation or "" - if (anim == self.animation.current + if (anim == self._current_animation or not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) and self.state ~= "die" then return end - self.animation.current = anim + self._current_animation = anim local a_start = self.animation[anim .. "_start"] local a_end @@ -3002,6 +3004,7 @@ end local function check_entity_cramming(self) local p = self.object:get_pos() + if not p then return end local oo = minetest.get_objects_inside_radius(p,1) local mobs = {} for _,o in pairs(oo) do @@ -3467,7 +3470,10 @@ local mob_activate = function(self, staticdata, def, dtime) def.textures = {def.textures} end - self.base_texture = def.textures[random(1, #def.textures)] + local c = 1 + if #def.textures > c then c = #def.textures end + + self.base_texture = def.textures[math.random(c)] self.base_mesh = def.mesh self.base_size = self.visual_size self.base_colbox = self.collisionbox diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index 58b8946f8..9aaa6bf48 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -513,6 +513,7 @@ if mobs_spawn then local mob_def = mob_library_worker_table[mob_index] local mob_type = minetest.registered_entities[mob_def.name].type local spawn_in_group = minetest.registered_entities[mob_def.name].spawn_in_group or 4 + local spawn_in_group_min = minetest.registered_entities[mob_def.name].spawn_in_group_min or 1 local mob_count_wide = count_mobs(pos,aoc_range,mob_type) local mob_count = count_mobs(spawning_position,32,mob_type) if mob_def diff --git a/mods/ENTITIES/mobs_mc/enderman.lua b/mods/ENTITIES/mobs_mc/enderman.lua index a57a82931..5445d59c4 100644 --- a/mods/ENTITIES/mobs_mc/enderman.lua +++ b/mods/ENTITIES/mobs_mc/enderman.lua @@ -219,6 +219,7 @@ local select_enderman_animation = function(animation_type) end local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false +local spawners = {} mcl_mobs:register_mob("mobs_mc:enderman", { description = S("Enderman"), @@ -263,20 +264,42 @@ mcl_mobs:register_mob("mobs_mc:enderman", { do_custom = function(self, dtime) -- PARTICLE BEHAVIOUR HERE. local enderpos = self.object:get_pos() - local chanceOfParticle = math.random(0, 1) - if chanceOfParticle == 1 then - minetest.add_particle({ - pos = {x=enderpos.x+math.random(-1,1)*math.random()/2,y=enderpos.y+math.random(0,3),z=enderpos.z+math.random(-1,1)*math.random()/2}, - velocity = {x=math.random(-.25,.25), y=math.random(-.25,.25), z=math.random(-.25,.25)}, - acceleration = {x=math.random(-.5,.5), y=math.random(-.5,.5), z=math.random(-.5,.5)}, - expirationtime = math.random(), - size = math.random(), - collisiondetection = true, - vertical = false, - texture = "mcl_portals_particle"..math.random(1, 5)..".png", - }) + if self._particle_timer and self._particle_timer >= 1 then + for _,player in pairs(minetest.get_connected_players()) do + if not spawners[player] then spawners[player] = {} end + local dst = vector.distance(player:get_pos(),enderpos) + if dst < 128 and not spawners[player][self.object] then + self._particle_timer = 0 + spawners[player][self.object] = minetest.add_particlespawner({ + amount = 5, + minpos = vector.new(-0.6,0,-0.6), + maxpos = vector.new(0.6,3,0.6), + minvel = vector.new(-0.25,-0.25,-0.25), + maxvel = vector.new(0.25,0.25,0.25), + minacc = vector.new(-0.5,-0.5,-0.5), + maxacc = vector.new(0.5,0.5,0.5), + minexptime = 0.2, + maxexptime = 3, + minsize = 0.2, + maxsize = 1.2, + collisiondetection = true, + vertical = false, + time = 0, + texture = "mcl_portals_particle"..math.random(1, 5)..".png", + attached = self.object, + playername = player:get_player_name(), + }) + elseif dst > 128 and spawners[player][self.object] then + minetest.delete_particlespawner(spawners[player][self.object]) + spawners[player][self.object] = nil + end + end + elseif not self._particle_timer then + self._particle_timer = 0 end + self._particle_timer = self._particle_timer + dtime -- RAIN DAMAGE / EVASIVE WARP BEHAVIOUR HERE. + enderpos = self.object:get_pos() local dim = mcl_worlds.pos_to_dimension(enderpos) if dim == "overworld" then if mcl_weather.state == "rain" or mcl_weather.state == "lightning" then @@ -312,24 +335,24 @@ mcl_mobs:register_mob("mobs_mc:enderman", { else return end -- AGRESSIVELY WARP/CHASE PLAYER BEHAVIOUR HERE. if self.state == "attack" then - --if (minetest.get_timeofday() * 24000) > 5001 and (minetest.get_timeofday() * 24000) < 19000 then - --self:teleport(nil) - --self.state = "" - --else - if self.attack then - local target = self.attack - local pos = target:get_pos() - if pos ~= nil then - if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then - self:teleport(target) - end + if self.attack then + local target = self.attack + local pos = target:get_pos() + if pos ~= nil then + if vector.distance(self.object:get_pos(), target:get_pos()) > 10 then + self:teleport(target) end end - --end + end + else --if not attacking try to tp to the dark + if minetest.get_node_light(enderpos) > minetest.LIGHT_MAX then + self:teleport(nil) + end end -- ARROW / DAYTIME PEOPLE AVOIDANCE BEHAVIOUR HERE. -- Check for arrows and people nearby. - local enderpos = self.object:get_pos() + + enderpos = self.object:get_pos() enderpos.y = enderpos.y + 1.5 local objs = minetest.get_objects_inside_radius(enderpos, 2) for n = 1, #objs do @@ -593,6 +616,13 @@ mcl_mobs:register_mob("mobs_mc:enderman", { attack_type = "dogfight", }) +minetest.register_on_leaveplayer(function(player) + for _,s in pairs(spawners[player]) do + minetest.delete_particlespawner(s) + end + spawners[player] = nil +end) + -- End spawn mcl_mobs:spawn_specific( diff --git a/mods/ENTITIES/mobs_mc/init.lua b/mods/ENTITIES/mobs_mc/init.lua index 120d7be0d..f32255d39 100644 --- a/mods/ENTITIES/mobs_mc/init.lua +++ b/mods/ENTITIES/mobs_mc/init.lua @@ -114,6 +114,7 @@ dofile(path .. "/squid.lua") -- Animation, sound and egg texture by daufinsyd dofile(path .. "/villager.lua") -- KrupnoPavel Mesh and animation by toby109tt / https://github.com/22i -- Illagers and witch +dofile(path .. "/pillager.lua") -- Mesh by KrupnoPavel and MrRar, animation by MrRar dofile(path .. "/villager_evoker.lua") -- Mesh and animation by toby109tt / https://github.com/22i dofile(path .. "/villager_vindicator.lua") -- Mesh and animation by toby109tt / https://github.com/22i dofile(path .. "/villager_zombie.lua") -- Mesh and animation by toby109tt / https://github.com/22i diff --git a/mods/ENTITIES/mobs_mc/locale/template.txt b/mods/ENTITIES/mobs_mc/locale/template.txt index 1f9261df6..b7087dffe 100644 --- a/mods/ENTITIES/mobs_mc/locale/template.txt +++ b/mods/ENTITIES/mobs_mc/locale/template.txt @@ -65,3 +65,4 @@ Nitwit= Cod= Salmon= Dolphin= +Pillager= diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.b3d b/mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.b3d new file mode 100644 index 000000000..18c1a06c4 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.b3d differ diff --git a/mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.blend b/mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.blend new file mode 100644 index 000000000..e0524ab74 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.blend differ diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index d4b6c12e6..cc20dadb1 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -13,12 +13,20 @@ local shoulders = { right = vector.new(3.75,10.5,0) } +local function table_get_rand(tbl) + local keys = {} + for k in pairs(tbl) do + table.insert(keys, k) + end + return tbl[keys[math.random(#keys)]] +end + local function get_random_mob_sound() local t = table.copy(minetest.registered_entities) table.shuffle(t) for _,e in pairs(t) do - if e.is_mob and e.sounds then - return e.sounds[math.random(#e.sounds)] + if e.is_mob and e.sounds and #e.sounds > 0 then + return table_get_rand(e.sounds) end end return minetest.registered_entities["mobs_mc:parrot"].sounds.random diff --git a/mods/ENTITIES/mobs_mc/pillager.lua b/mods/ENTITIES/mobs_mc/pillager.lua new file mode 100644 index 000000000..c90aa3821 --- /dev/null +++ b/mods/ENTITIES/mobs_mc/pillager.lua @@ -0,0 +1,122 @@ +local S = minetest.get_translator("mobs_mc") + +local function reload(self) + if not self.object:get_pos() then return end + minetest.sound_play("mcl_bows_crossbow_drawback_1", {object = self.object, max_hear_distance=16}, true) + local props = self.object:get_properties() + if not props then return end + props.textures[2] = "mcl_bows_crossbow_3.png^[resize:16x16" + self.object:set_properties(props) +end + +local function reset_animation(self, animation) + if not self.object:get_pos() or self._current_animation ~= animation then return end + self._current_animation = "stand_reload" -- Mobs Redo won't set the animation unless we do this + mcl_mobs:set_animation(self, animation) +end + +pillager = { + description = S("Pillager"), + type = "monster", + spawn_class = "hostile", + hp_min = 24, + hp_max = 24, + xp_min = 6, + xp_max = 6, + breath_max = -1, + eye_height = 1.5, + shoot_interval = 3, + shoot_offset = 1.5, + armor = {fleshy = 100}, + collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3}, + pathfinding = 1, + group_attack = true, + visual = "mesh", + mesh = "mobs_mc_pillager.b3d", + visual_size = {x=2.75, y=2.75}, + makes_footstep_sound = true, + walk_velocity = 1.2, + run_velocity = 4, + view_range = 16, + fear_height = 4, + arrow = "mcl_bows:arrow_entity", + attack_type = "dogshoot", -- Alternate punching/shooting + reach = 0, -- Punching max distance + damage = 0, -- Punching damage + dogshoot_switch = 1, -- Start of shooting + dogshoot_count_max = 5, -- Max time spent shooting (standing) + dogshoot_count2_max = 1, -- Max time spent punching (running) + sounds = { + random = "mobs_mc_pillager_grunt2", + war_cry = "mobs_mc_pillager_grunt1", + death = "mobs_mc_pillager_ow2", + damage = "mobs_mc_pillager_ow1", + distance = 16, + }, + textures = { + { + "mobs_mc_pillager.png", -- Skin + "mcl_bows_crossbow_3.png^[resize:16x16", -- Wielded item + } + }, + drops = { + { + name = "mcl_bows:arrow", + chance = 1, + min = 0, + max = 2, + looting = "common", + }, + { + name = "mcl_bows:crossbow", + chance = 100 / 8.5, + min = 1, + max = 1, + looting = "rare", + }, + }, + animation = { + unloaded_walk_start = 1, unloaded_walk_end = 40, + unloaded_stand_start = 41, unloaded_stand_end = 60, + reload_stand_start = 61, reload_stand_end = 100, reload_stand_speed = 20, + stand_start = 101, stand_end = 109, stand_speed = 6, + walk_start = 111, walk_end = 150, walk_speed = 30, + run_start = 111, run_end = 150, run_speed = 50, + reload_run_start = 151, reload_run_end = 190, reload_run_speed = 20, + die_start = 191, die_end = 192, die_speed = 15, + stand_unloaded_start = 40, stand_unloaded_end = 59, + die_loop = false, + }, + shoot_arrow = function(self, pos, dir) + minetest.sound_play("mcl_bows_crossbow_shoot", {object = self.object, max_hear_distance=16}, true) + local props = self.object:get_properties() + props.textures[2] = "mcl_bows_crossbow_0.png^[resize:16x16" + self.object:set_properties(props) + local old_anim = self._current_animation + if old_anim == "run" or old_anim == "walk" then + mcl_mobs:set_animation(self, "reload_run") + end + if old_anim == "stand" then + mcl_mobs:set_animation(self, "reload_stand") + end + self._current_animation = old_anim -- Mobs Redo will imediately reset the animation otherwise + minetest.after(1, reload, self) + minetest.after(2, reset_animation, self, old_anim) + + -- 2-4 damage per arrow + local dmg = math.max(4, math.random(2, 8)) + mcl_bows_s.shoot_arrow_crossbow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) + + -- While we are at it, change the sounds since there is no way to do this in Mobs Redo + if self.sounds and self.sounds.random then + self.sounds = table.copy(self.sounds) + self.sounds.random = "mobs_mc_pillager_grunt" .. math.random(2) + end + + -- Randomize reload time + self.shoot_interval = math.random(3, 4) + end, +} + +mcl_mobs:register_mob("mobs_mc:pillager", pillager) +mcl_mobs:register_egg("mobs_mc:pillager", S("Pillager"), "mobs_mc_spawn_icon_pillager.png", 0) diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt1.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt1.ogg new file mode 100644 index 000000000..38ef59445 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt1.ogg differ diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt2.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt2.ogg new file mode 100644 index 000000000..b5766734e Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt2.ogg differ diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow1.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow1.ogg new file mode 100644 index 000000000..37e7620ef Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow1.ogg differ diff --git a/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow2.ogg b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow2.ogg new file mode 100644 index 000000000..0983ae4bb Binary files /dev/null and b/mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow2.ogg differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png new file mode 100644 index 000000000..b46f16e1b Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png differ diff --git a/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png new file mode 100644 index 000000000..67dbfe418 Binary files /dev/null and b/mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png differ diff --git a/mods/ENTITIES/mobs_mc/tropical_fish.lua b/mods/ENTITIES/mobs_mc/tropical_fish.lua index d963665b2..fb321de96 100644 --- a/mods/ENTITIES/mobs_mc/tropical_fish.lua +++ b/mods/ENTITIES/mobs_mc/tropical_fish.lua @@ -72,7 +72,7 @@ local tropical_fish = { collisionbox = {-0.2, 0.0, -0.2, 0.2, 0.1, 0.2}, visual = "mesh", mesh = "extra_mobs_tropical_fish_a.b3d", - textures = {}, -- to be populated on_spawn + textures = { "extra_mobs_tropical_fish_a.png" }, -- to be populated on_spawn sounds = {}, animation = { stand_start = 0, diff --git a/mods/HUD/mcl_credits/people.lua b/mods/HUD/mcl_credits/people.lua index 4658393b6..e5f418769 100644 --- a/mods/HUD/mcl_credits/people.lua +++ b/mods/HUD/mcl_credits/people.lua @@ -28,6 +28,11 @@ return { "Code-Sploit", "NO11", "kabou", + "rudzik8", + "chmodsayshello", + "PrarieWind", + "RandomLegoBrick", + "SumianVoice", }}, {S("Contributors"), 0x52FF00, { "Laurent Rocher", @@ -72,6 +77,12 @@ return { "Sven792", "aldum", "Dieter44", + "Pepebotella", + "MrRar", + "Lazerbeak12345", + "mrminer", + "Thunder1035", + "opfromthestart", }}, {S("MineClone5"), 0xA60014, { "kay27", @@ -79,10 +90,12 @@ return { "epCode", "NO11", "j45", + "chmodsayshello", "3raven", "PrarieWind", "Gustavo1", "CableGuy67", + "MrRar", }}, {S("Mineclonia"), 0xFFFFFF, { "erlehmann", @@ -135,6 +148,9 @@ return { "yutyo", "NO11", "kay27", + "MysticTempest", + "RandomLegoBrick", + "cora", }}, {S("Translations"), 0x00FF60, { "Wuzzy", @@ -144,6 +160,8 @@ return { "pitchum", "todoporlalibertad", "Marcin Serwin", + "Pepebotella", + "Emojigit", }}, {S("Funders"), 0xF7FF00, { "40W", @@ -151,7 +169,8 @@ return { {S("Special thanks"), 0x00E9FF, { "celeron55 for creating Minetest", "Jordach for the jukebox music compilation from Big Freaking Dig", + "wsor for working tirelessly in the shadows for the good of all of us, particularly helping with solving contentDB and copyright issues.", "The workaholics who spent way too much time writing for the Minecraft Wiki. It's an invaluable resource for creating this game", "Notch and Jeb for being the major forces behind Minecraft", }}, -} +} \ No newline at end of file diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d b/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d index b3a943f46..9c1b290a6 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d and b/mods/ITEMS/mcl_armor/models/mcl_armor_character.b3d differ diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend b/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend index a613eef89..b41b3c575 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend and b/mods/ITEMS/mcl_armor/models/mcl_armor_character.blend differ diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d index 4e17ee341..15a131e94 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d and b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.b3d differ diff --git a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend index b0494efbf..8c16536b2 100644 Binary files a/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend and b/mods/ITEMS/mcl_armor/models/mcl_armor_character_female.blend differ diff --git a/mods/ITEMS/mcl_fishing/init.lua b/mods/ITEMS/mcl_fishing/init.lua index 20f4e6f26..546ad7eea 100644 --- a/mods/ITEMS/mcl_fishing/init.lua +++ b/mods/ITEMS/mcl_fishing/init.lua @@ -390,7 +390,7 @@ minetest.register_tool("mcl_fishing:fishing_rod", { _doc_items_usagehelp = S("Rightclick to launch the bobber. When it sinks right-click again to reel in an item. Who knows what you're going to catch?"), groups = { tool=1, fishing_rod=1, enchantability=1 }, inventory_image = "mcl_fishing_fishing_rod.png", - wield_image = "mcl_fishing_fishing_rod.png^[transformR270", + wield_image = "mcl_fishing_fishing_rod.png^[transformFY^[transformR90", wield_scale = { x = 1.5, y = 1.5, z = 1 }, stack_max = 1, on_place = fish, diff --git a/mods/ITEMS/mcl_fishing/textures/mcl_fishing_fishing_rod.png b/mods/ITEMS/mcl_fishing/textures/mcl_fishing_fishing_rod.png index 2fbcc7344..564188f7e 100644 Binary files a/mods/ITEMS/mcl_fishing/textures/mcl_fishing_fishing_rod.png and b/mods/ITEMS/mcl_fishing/textures/mcl_fishing_fishing_rod.png differ diff --git a/mods/ITEMS/mcl_grindstone/init.lua b/mods/ITEMS/mcl_grindstone/init.lua index f373070cd..00c373536 100644 --- a/mods/ITEMS/mcl_grindstone/init.lua +++ b/mods/ITEMS/mcl_grindstone/init.lua @@ -1,9 +1,203 @@ +-- Code based from mcl_anvils + local S = minetest.get_translator(minetest.get_current_modname()) +local MAX_WEAR = 65535 + +-- formspecs +local function get_grindstone_formspec() + return "size[9,8.75]".. + "image[3,1.5;1.5,1;gui_crafting_arrow.png]".. + "label[0,4.0;"..minetest.formspec_escape(minetest.colorize("#313131", S("Inventory"))).."]".. + "label[1,0.1;"..minetest.formspec_escape(minetest.colorize("#313131", S("Repair & Disenchant"))).."]".. + "list[context;main;0,0;8,4;]".. + "list[current_player;main;0,4.5;9,3;9]".. + mcl_formspec.get_itemslot_bg(0,4.5,9,3).. + "list[current_player;main;0,7.74;9,1;]".. + mcl_formspec.get_itemslot_bg(0,7.74,9,1).. + "list[context;input;1,1;1,1;]".. + mcl_formspec.get_itemslot_bg(1,1,1,1).. + "list[context;input;1,2;1,1;1]".. + mcl_formspec.get_itemslot_bg(1,2,1,1).. + "list[context;output;6,1.5;1,1;]".. + mcl_formspec.get_itemslot_bg(6,1.5,1,1).. + "listring[context;output]".. + "listring[current_player;main]".. + "listring[context;input]".. + "listring[current_player;main]" +end + +-- Creates a new item with the wear of the items and custom name +local function create_new_item(name_item, meta, wear) + local new_item = ItemStack(name_item) + if wear ~= nil then + new_item:set_wear(wear) + end + local new_meta = new_item:get_meta() + new_meta:set_string("name", meta:get_string("name")) + tt.reload_itemstack_description(new_item) + return new_item +end + +-- If an item has an enchanment then remove "_enchanted" from the name +local function remove_enchant_name(stack) + if mcl_enchanting.is_enchanted(stack:get_name()) then + local name = stack:get_name() + return name.sub(name, 1, -11) + else + return stack:get_name() + end +end + +-- If an input has a curse transfer it to the new item +local function transfer_curse(old_itemstack, new_itemstack) + local enchants = mcl_enchanting.get_enchantments(old_itemstack) + for enchant, level in pairs(enchants) do + if mcl_enchanting.enchantments[enchant].curse == true then + new_itemstack = mcl_enchanting.enchant(new_itemstack, enchant, level) + end + end + return new_itemstack +end + +-- Depending on an enchantment level and isn't a curse multiply xp given +local function calculate_xp(stack) + local xp = 0 + local enchants = mcl_enchanting.get_enchantments(stack) + for enchant, level in pairs(enchants) do + if level > 0 and mcl_enchanting.enchantments[enchant].curse == false then + -- Add a bit of uniform randomisation + xp = xp + math.random(7, 13) * level + end + end + return xp +end + +-- Helper function to make sure update_grindstone_slots NEVER overstacks the output slot +local function fix_stack_size(stack) + if not stack or stack == "" then return "" end + local count = stack:get_count() + local max_count = stack:get_stack_max() + + if count > max_count then + stack:set_count(max_count) + count = max_count + end + return count +end + + +-- Update the inventory slots of an grindstone node. +-- meta: Metadata of grindstone node +local function update_grindstone_slots(meta) + local inv = meta:get_inventory() + local input1 = inv:get_stack("input", 1) + local input2 = inv:get_stack("input", 2) + local meta = input1:get_meta() + + local new_output + + -- Both input slots are occupied + if (not input1:is_empty() and not input2:is_empty()) then + local def1 = input1:get_definition() + local def2 = input2:get_definition() + -- Remove enchant name if they have one + local name1 = remove_enchant_name(input1) + local name2 = remove_enchant_name(input2) + + -- Calculate repair + local function calculate_repair(dur1, dur2) + -- Grindstone gives a 5% bonus to durability + local new_durability = (MAX_WEAR - dur1) + (MAX_WEAR - dur2) * 1.05 + return math.max(0, math.min(MAX_WEAR, MAX_WEAR - new_durability)) + end + + -- Check if both are tools and have the same tool type + if def1.type == "tool" and def2.type == "tool" and name1 == name2 then + local new_wear = calculate_repair(input1:get_wear(), input2:get_wear()) + local new_item = create_new_item(name1, meta, new_wear) + -- Transfer curses if both items have any + new_output = transfer_curse(input1, new_item) + new_output = transfer_curse(input2, new_output) + else + new_output = "" + end + -- Check if at least one input has an item + -- Check if the item is's an enchanted book or tool + elseif (not input1:is_empty() and input2:is_empty()) or (input1:is_empty() and not input2:is_empty()) then + if input2:is_empty() then + local def1 = input1:get_definition() + local meta = input1:get_meta() + if def1.type == "tool" and mcl_enchanting.is_enchanted(input1:get_name()) then + local name = remove_enchant_name(input1) + local wear = input1:get_wear() + local new_item = create_new_item(name, meta, wear) + new_output = transfer_curse(input1, new_item) + elseif input1:get_name() == "mcl_enchanting:book_enchanted" then + new_item = create_new_item("mcl_books:book", meta, nil) + new_output = transfer_curse(input1, new_item) + else + new_output = "" + end + else + local def2 = input2:get_definition() + local meta = input2:get_meta() + if def2.type == "tool" and mcl_enchanting.is_enchanted(input2:get_name()) then + local name = remove_enchant_name(input2) + local wear = input2:get_wear() + local new_item = create_new_item(name, meta, wear) + new_output = transfer_curse(input2, new_item) + elseif input2:get_name() == "mcl_enchanting:book_enchanted" then + new_item = create_new_item("mcl_books:book", meta, nil) + new_output = transfer_curse(input2, new_item) + else + new_output = "" + end + end + else + new_output = "" + end + + -- Set the new output slot + if new_output then + fix_stack_size(new_output) + inv:set_stack("output", 1, new_output) + end +end + +-- Drop any items inside the grindstone if destroyed +local function drop_grindstone_items(pos, meta) + local inv = meta:get_inventory() + for i=1, inv:get_size("input") do + local stack = inv:get_stack("input", i) + if not stack:is_empty() then + local p = {x=pos.x+math.random(0, 10)/10-0.5, y=pos.y, z=pos.z+math.random(0, 10)/10-0.5} + minetest.add_item(p, stack) + end + end +end + +local node_box = { + type = "fixed", + -- created with nodebox editor + fixed = { + {-0.25, -0.25, -0.375, 0.25, 0.5, 0.375}, + {-0.375, -0.0625, -0.1875, -0.25, 0.3125, 0.1875}, + {0.25, -0.0625, -0.1875, 0.375, 0.3125, 0.1875}, + {0.25, -0.5, -0.125, 0.375, -0.0625, 0.125}, + {-0.375, -0.5, -0.125, -0.25, -0.0625, 0.125}, + } +} + minetest.register_node("mcl_grindstone:grindstone", { description = S("Grindstone"), _tt_help = S("Used to disenchant/fix tools"), - _doc_items_longdesc = S("This is currently a decorative block which serves as the weapon smith's work station. In minecraft this is used to disenchant/fix tools howerver this has not yet been implemented"), + _doc_items_longdesc = S("Grindstone disenchants tools and armour except for curses, and repairs two items of the same type it is also the weapon smith's work station."), + _doc_items_usagehelp = S("To use the grindstone, rightclick it, Two input slots (on the left) and a single output slot.").."\n".. + S("To disenchant an item place enchanted item in one of the input slots and take the disenchanted item from the output.").."\n".. + S("To repair a tool you need a tool of the same type and material, put both items in the input slot and the output slot will combine two items durabilities with 5% bonus.").."\n".. + S("If both items have enchantments the player will get xp from both items from the disenchant.").."\n".. + S("Curses cannot be removed and will be transfered to the new repaired item, if both items have a different curse the curses will be combined."), tiles = { "grindstone_top.png", "grindstone_top.png", @@ -14,18 +208,128 @@ minetest.register_node("mcl_grindstone:grindstone", { }, drawtype = "nodebox", paramtype2 = "facedir", - node_box = { - type = "fixed", - -- created with nodebox editor - fixed = { - {-0.25, -0.25, -0.375, 0.25, 0.5, 0.375}, - {-0.375, -0.0625, -0.1875, -0.25, 0.3125, 0.1875}, - {0.25, -0.0625, -0.1875, 0.375, 0.3125, 0.1875}, - {0.25, -0.5, -0.125, 0.375, -0.0625, 0.125}, - {-0.375, -0.5, -0.125, -0.25, -0.0625, 0.125}, - } - }, + node_box = node_box, + selection_box = node_box, + collision_box = node_box, + sounds = mcl_sounds.node_sound_stone_defaults(), groups = {pickaxey = 1, deco_block = 1}, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + local meta = minetest.get_meta(pos) + local meta2 = meta:to_table() + meta:from_table(oldmetadata) + drop_grindstone_items(pos, meta) + meta:from_table(meta2) + end, + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + local name = player:get_player_name() + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return 0 + else + return stack:get_count() + end + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + local name = player:get_player_name() + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return 0 + elseif listname == "output" then + return 0 + else + return stack:get_count() + end + end, + allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + local name = player:get_player_name() + if minetest.is_protected(pos, name) then + minetest.record_protection_violation(pos, name) + return 0 + elseif to_list == "output" then + return 0 + elseif from_list == "output" and to_list == "input" then + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if inv:get_stack(to_list, to_index):is_empty() then + return count + else + return 0 + end + else + return count + end + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + update_grindstone_slots(meta) + end, + on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) + local meta = minetest.get_meta(pos) + if from_list == "output" and to_list == "input" then + local inv = meta:get_inventory() + for i=1, inv:get_size("input") do + if i ~= to_index then + local istack = inv:get_stack("input", i) + istack:set_count(math.max(0, istack:get_count() - count)) + inv:set_stack("input", i, istack) + end + end + end + update_grindstone_slots(meta) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + local meta = minetest.get_meta(pos) + if listname == "output" then + local xp_earnt = 0 + local inv = meta:get_inventory() + local input1 = inv:get_stack("input", 1) + local input2 = inv:get_stack("input", 2) + -- Both slots occupied? + if not input1:is_empty() and not input2:is_empty() then + -- Get xp earnt from the enchanted items + xp_earnt = calculate_xp(input1) + calculate_xp(input1) + input1:take_item() + input2:take_item() + inv:set_stack("input", 1, input1) + inv:set_stack("input", 2, input2) + else + -- If only one input item + if not input1:is_empty() then + xp_earnt = calculate_xp(input1) + input1:set_count(math.max(0, input1:get_count() - stack:get_count())) + inv:set_stack("input", 1, input1) + end + if not input2:is_empty() then + xp_earnt = calculate_xp(input2) + input2:set_count(math.max(0, input2:get_count() - stack:get_count())) + inv:set_stack("input", 2, input2) + end + end + -- Give the player xp + if mcl_experience.throw_xp and xp_earnt > 0 then + mcl_experience.throw_xp(pos, xp_earnt) + end + elseif listname == "input" then + update_grindstone_slots(meta) + end + end, + + on_construct = function(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_size("input", 2) + inv:set_size("output", 1) + local form = get_grindstone_formspec() + meta:set_string("formspec", form) + end, + on_rightclick = function(pos, node, player, itemstack) + if not player:get_player_control().sneak then + local meta = minetest.get_meta(pos) + update_grindstone_slots(meta) + meta:set_string("formspec", get_grindstone_formspec()) + end + end, _mcl_blast_resistance = 6, _mcl_hardness = 2 }) @@ -36,4 +340,4 @@ minetest.register_craft({ { "mcl_core:stick", "mcl_stairs:slab_stone_rough", "mcl_core:stick"}, { "group:wood", "", "group:wood"}, } -}) \ No newline at end of file +}) diff --git a/mods/ITEMS/mcl_grindstone/locale/template.txt b/mods/ITEMS/mcl_grindstone/locale/template.txt new file mode 100644 index 000000000..089e41c12 --- /dev/null +++ b/mods/ITEMS/mcl_grindstone/locale/template.txt @@ -0,0 +1,10 @@ +Inventory= +Repair & Disenchant= +Grindstone= +Used to disenchant/fix tools= +Grindstone disenchants tools and armour except for curses, and repairs two items of the same type it is also the weapon smith's work station.= +To use the grindstone, rightclick it, Two input slots (on the left) and a single output slot.= +To disenchant an item place enchanted item in one of the input slots and take the disenchanted item from the output.= +To repair a tool you need a tool of the same type and material, put both items in the input slot and the output slot will combine two items durabilities with 5% bonus.= +If both items have enchantments the player will get xp from both items from the disenchant.= +Curses cannot be removed and will be transfered to the new repaired item, if both items have a different curse the curses will be combined.= \ No newline at end of file diff --git a/mods/ITEMS/mcl_grindstone/mod.conf b/mods/ITEMS/mcl_grindstone/mod.conf index 154de013f..66773c57f 100644 --- a/mods/ITEMS/mcl_grindstone/mod.conf +++ b/mods/ITEMS/mcl_grindstone/mod.conf @@ -1,3 +1,4 @@ name = mcl_grindstone -author = TheRandomLegoBrick -description = Adds a cool looking block for the weaponsmiths jobsite \ No newline at end of file +author = TheRandomLegoBrick, ChrisPHP +depends = mcl_experience, mcl_sounds +description = Add block that disenchants tools and armour except for curses, and repairs two items of the same type it is also the weapon smith's work station. diff --git a/mods/ITEMS/mcl_grindstone/textures/gui_crafting_arrow.png b/mods/ITEMS/mcl_grindstone/textures/gui_crafting_arrow.png new file mode 100644 index 000000000..93ce1e1b9 Binary files /dev/null and b/mods/ITEMS/mcl_grindstone/textures/gui_crafting_arrow.png differ diff --git a/mods/ITEMS/mcl_maps/init.lua b/mods/ITEMS/mcl_maps/init.lua index fb13625d5..7b22ffef1 100644 --- a/mods/ITEMS/mcl_maps/init.lua +++ b/mods/ITEMS/mcl_maps/init.lua @@ -227,6 +227,7 @@ filled_wield_def.drawtype = "mesh" filled_wield_def.node_placement_prediction = "" filled_wield_def.range = minetest.registered_items[""].range filled_wield_def.on_place = mcl_util.call_on_rightclick +filled_wield_def._mcl_wieldview_item = "mcl_maps:filled_map" for _, texture in pairs(mcl_skins.list) do local def = table.copy(filled_wield_def) diff --git a/mods/ITEMS/mcl_mobitems/init.lua b/mods/ITEMS/mcl_mobitems/init.lua index 2f3bd3c01..d5b43058e 100644 --- a/mods/ITEMS/mcl_mobitems/init.lua +++ b/mods/ITEMS/mcl_mobitems/init.lua @@ -321,7 +321,7 @@ minetest.register_tool("mcl_mobitems:carrot_on_a_stick", { _tt_help = S("Lets you ride a saddled pig"), _doc_items_longdesc = S("A carrot on a stick can be used on saddled pigs to ride them."), _doc_items_usagehelp = S("Place it on a saddled pig to mount it. You can now ride the pig like a horse. Pigs will also walk towards you when you just wield the carrot on a stick."), - wield_image = "mcl_mobitems_carrot_on_a_stick.png", + wield_image = "mcl_mobitems_carrot_on_a_stick.png^[transformFY^[transformR90", inventory_image = "mcl_mobitems_carrot_on_a_stick.png", groups = { transport = 1 }, _mcl_toollike_wield = true, diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua index eb7d45ff9..3ad2ada51 100644 --- a/mods/ITEMS/mcl_shields/init.lua +++ b/mods/ITEMS/mcl_shields/init.lua @@ -31,12 +31,12 @@ minetest.register_tool("mcl_shields:shield", { shield = 1, weapon = 1, enchantability = -1, - no_wieldview = 1, offhand_item = 1, }, sound = {breaks = "default_tool_breaks"}, _repair_material = "group:wood", wield_scale = vector.new(2, 2, 2), + _mcl_wieldview_item = "", }) local function wielded_item(obj, i) @@ -438,7 +438,6 @@ for _, colortab in pairs(mcl_banners.colors) do shield = 1, weapon = 1, enchantability = -1, - no_wieldview = 1, not_in_creative_inventory = 1, offhand_item = 1, }, @@ -446,6 +445,7 @@ for _, colortab in pairs(mcl_banners.colors) do _repair_material = "group:wood", wield_scale = vector.new(2, 2, 2), _shield_color = colortab[4], + _mcl_wieldview_item = "", }) local banner = "mcl_banners:banner_item_" .. color diff --git a/mods/ITEMS/mcl_smithing_table/init.lua b/mods/ITEMS/mcl_smithing_table/init.lua index f32cb8c28..dbb6c620f 100644 --- a/mods/ITEMS/mcl_smithing_table/init.lua +++ b/mods/ITEMS/mcl_smithing_table/init.lua @@ -7,19 +7,15 @@ mcl_smithing_table = {} -- Function to upgrade diamond tool/armor to netherite tool/armor function mcl_smithing_table.upgrade_item(itemstack) - itemstack = ItemStack(itemstack) -- Copy the stack - local def = itemstack:get_definition() if not def or not def._mcl_upgradable then return end - local itemname = itemstack:get_name() + local upgrade_item = itemname:gsub("diamond", "netherite") - local upgrade_item = def._mcl_upgrade_item or itemname:gsub("diamond", "netherite") - - if upgrade_item == itemname then + if def._mcl_upgrade_item and upgrade_item == itemname then return end diff --git a/mods/MAPGEN/mcl_structures/pillager_outpost.lua b/mods/MAPGEN/mcl_structures/pillager_outpost.lua index 596aa66c7..4646b96ab 100644 --- a/mods/MAPGEN/mcl_structures/pillager_outpost.lua +++ b/mods/MAPGEN/mcl_structures/pillager_outpost.lua @@ -57,11 +57,25 @@ mcl_structures.register_structure("pillager_outpost",{ after_place = function(p,def,pr) local p1 = vector.offset(p,-7,0,-7) local p2 = vector.offset(p,7,14,7) + local spawnon = {"mcl_core:stripped_oak"} + local sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon) for _,n in pairs(minetest.find_nodes_in_area(p1,p2,{"group:wall"})) do local def = minetest.registered_nodes[minetest.get_node(n).name:gsub("_%d+$","")] if def and def.on_construct then def.on_construct(n) end end + if sp and #sp > 0 then + for i=1,5 do + local pos = sp[pr:next(1,#sp)] + if pos then + minetest.add_entity(pos,"mobs_mc:pillager") + end + end + local pos = sp[pr:next(1,#sp)] + if pos then + minetest.add_entity(pos,"mobs_mc:evoker") + end + end end }) diff --git a/mods/PLAYER/mcl_death_drop/init.lua b/mods/PLAYER/mcl_death_drop/init.lua index 5ea548ecc..9b1bad75f 100644 --- a/mods/PLAYER/mcl_death_drop/init.lua +++ b/mods/PLAYER/mcl_death_drop/init.lua @@ -33,21 +33,20 @@ minetest.register_on_dieplayer(function(player) end local listname = mcl_death_drop.registered_dropped_lists[l].listname local drop = mcl_death_drop.registered_dropped_lists[l].drop + local dropspots = minetest.find_nodes_in_area(vector.offset(pos,-3,0,-3),vector.offset(pos,3,0,3),{"air"}) + if #dropspots == 0 then + table.insert(dropspots,pos) + end if inv then for i, stack in ipairs(inv:get_list(listname)) do - local x = random(0, 9)/3 - local z = random(0, 9)/3 - pos.x = pos.x + x - pos.z = pos.z + z + local p = vector.offset(dropspots[math.random(#dropspots)],math.random()-0.5,math.random()-0.5,math.random()-0.5) if not void_deadly and drop and not mcl_enchanting.has_enchantment(stack, "curse_of_vanishing") then local def = minetest.registered_items[stack:get_name()] if def and def.on_drop then - stack = def.on_drop(stack, player, pos) + stack = def.on_drop(stack, player, p) end - minetest.add_item(pos, stack) + minetest.add_item(p, stack) end - pos.x = pos.x - x - pos.z = pos.z - z end inv:set_list(listname, {}) end diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index 4824bc9e3..f717d4ba1 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -103,10 +103,6 @@ function mcl_player.player_set_armor(player, texture) set_texture(player, 2, texture) end -function mcl_player.player_set_wielditem(player, texture) - set_texture(player, 3, texture) -end - function mcl_player.get_player_formspec_model(player, x, y, w, h, fsname) local name = player:get_player_name() local model = player_model[name] diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 8756846ce..be95455c9 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -359,15 +359,17 @@ minetest.register_globalstep(function(dtime) end if wielded_def and wielded_def._mcl_toollike_wield then - set_bone_position_conditional(player,"Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0)) + set_bone_position_conditional(player,"Wield_Item", vector.new(0,4.7,3.1), vector.new(-90,225,90)) elseif string.find(wielded:get_name(), "mcl_bows:bow") then - set_bone_position_conditional(player,"Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20)) + set_bone_position_conditional(player,"Wield_Item", vector.new(1,4,0), vector.new(90,130,115)) elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then - set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(64,90,0)) + set_bone_position_conditional(player,"Wield_Item", vector.new(0,5.2,1.2), vector.new(0,180,73)) elseif string.find(wielded:get_name(), "mcl_bows:crossbow") then - set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(90,90,0)) + set_bone_position_conditional(player,"Wield_Item", vector.new(0,5.2,1.2), vector.new(0,180,45)) + elseif wielded_def.inventory_image == "" then + set_bone_position_conditional(player,"Wield_Item", vector.new(0,6,2), vector.new(180,-45,0)) else - set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90)) + set_bone_position_conditional(player,"Wield_Item", vector.new(0,5.3,2), vector.new(90,0,0)) end -- controls right and left arms pitch when shooting a bow or blocking diff --git a/mods/PLAYER/mcl_wieldview/README.txt b/mods/PLAYER/mcl_wieldview/README.txt index 183e8c6d5..b6de5b208 100644 --- a/mods/PLAYER/mcl_wieldview/README.txt +++ b/mods/PLAYER/mcl_wieldview/README.txt @@ -1,21 +1,13 @@ -[mod] visible wielded items [wieldview] +[mod] visible wielded items [mcl_wieldview] ======================================= Makes hand wielded items visible to other players. -default settings: [minetest.conf] - -# Set number of seconds between visible wielded item updates. -wieldview_update_time = 2 - -# Show nodes as tiles, disabled by default -wieldview_node_tiles = false - Info for modders ################ -Wield image transformation: To apply a simple transformation to the item in -hand, add the group “wieldview_transform” to the item definition. The group -rating equals one of the numbers used for the [transform texture modifier -of the Lua API. +Register an item with the property "_mcl_wieldview_item" to change the third person wield view appearance of the item. +"_mcl_wieldview_item" should be set to an item name that will be shown by the wield view instead of the item. +If you use an empty string, nothing will be shown. + diff --git a/mods/PLAYER/mcl_wieldview/init.lua b/mods/PLAYER/mcl_wieldview/init.lua index ff70445e3..3a646a18a 100644 --- a/mods/PLAYER/mcl_wieldview/init.lua +++ b/mods/PLAYER/mcl_wieldview/init.lua @@ -1,126 +1,64 @@ -local get_connected_players = minetest.get_connected_players -local get_item_group = minetest.get_item_group - -mcl_wieldview = { - players = {} -} - -function mcl_wieldview.get_item_texture(itemname) - if itemname == "" or minetest.get_item_group(itemname, "no_wieldview") ~= 0 then - return - end - - local def = minetest.registered_items[itemname] - if not def then - return - end - - local inv_image = def.inventory_image - if inv_image == "" then - return - end - - local texture = inv_image - - local transform = get_item_group(itemname, "wieldview_transform") - if transform then - -- This actually works with groups ratings because transform1, transform2, etc. - -- have meaning and transform0 is used for identidy, so it can be ignored - texture = texture .. "^[transform" .. transform - end - - return texture -end - -function mcl_wieldview.update_wielded_item(player) - if not player then - return - end - local itemstack = player:get_wielded_item() - local itemname = itemstack:get_name() - - local def = mcl_wieldview.players[player] - - if def.item == itemname then - return - end - - def.item = itemname - def.texture = mcl_wieldview.get_item_texture(itemname) or "blank.png" - - mcl_player.player_set_wielditem(player, def.texture) -end - -minetest.register_on_joinplayer(function(player) - mcl_wieldview.players[player] = {item = "", texture = "blank.png"} - - minetest.after(0, function() - if not player:is_player() then - return - end - - mcl_wieldview.update_wielded_item(player) - - local itementity = minetest.add_entity(player:get_pos(), "mcl_wieldview:wieldnode") - itementity:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 0, 45)) - itementity:get_luaentity().wielder = player - end) -end) - -minetest.register_on_leaveplayer(function(player) - mcl_wieldview.players[player] = nil -end) - -minetest.register_globalstep(function() - local players = get_connected_players() - for i = 1, #players do - mcl_wieldview.update_wielded_item(players[i]) - end -end) - -minetest.register_entity("mcl_wieldview:wieldnode", { +minetest.register_entity("mcl_wieldview:wieldview", { initial_properties = { hp_max = 1, visual = "wielditem", physical = false, - textures = {""}, - automatic_rotate = 1.5, - is_visible = true, + is_visible = false, pointable = false, collide_with_objects = false, static_save = false, collisionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21}, selectionbox = {-0.21, -0.21, -0.21, 0.21, 0.21, 0.21}, visual_size = {x = 0.21, y = 0.21}, - }, - - itemstring = "", - - on_step = function(self) - if self.wielder:is_player() then - local def = mcl_wieldview.players[self.wielder] - local itemstring = def.item - - if self.itemstring ~= itemstring then - local itemdef = minetest.registered_items[itemstring] - self.object:set_properties({glow = itemdef and itemdef.light_source or 0}) - - -- wield item as cubic - if def.texture == "blank.png" then - self.object:set_properties({textures = {itemstring}}) - -- wield item as flat - else - self.object:set_properties({textures = {""}}) - end - - if minetest.get_item_group(itemstring, "no_wieldview") ~= 0 then - self.object:set_properties({textures = {""}}) - end - - self.itemstring = itemstring - end - else - self.object:remove() - end - end, + } }) + +local wieldview_luaentites = {} + +local function update_wieldview_entity(player) + local luaentity = wieldview_luaentites[player] + if luaentity and luaentity.object:get_yaw() then + local item = player:get_wielded_item():get_name() + + if item == luaentity._item then return end + + luaentity._item = item + + local def = player:get_wielded_item():get_definition() + if def and def._mcl_wieldview_item then + item = def._mcl_wieldview_item + end + + local item_def = minetest.registered_items[item] + luaentity.object:set_properties({ + glow = item_def and item_def.light_source or 0, + wield_item = item, + is_visible = item ~= "" + }) + else + -- If the player is running through an unloaded area, + -- the wieldview entity will sometimes get unloaded. + -- This code path is also used to initalize the wieldview. + -- Creating entites from minetest.register_on_joinplayer + -- is unreliable as of Minetest 5.6 + local obj_ref = minetest.add_entity(player:get_pos(), "mcl_wieldview:wieldview") + if not obj_ref then return end + obj_ref:set_attach(player, "Wield_Item") + --obj_ref:set_attach(player, "Hand_Right", vector.new(0, 1, 0), vector.new(90, 45, 90)) + wieldview_luaentites[player] = obj_ref:get_luaentity() + end +end + +minetest.register_on_leaveplayer(function(player) + if wieldview_luaentites[player] then + wieldview_luaentites[player].object:remove() + end + wieldview_luaentites[player] = nil +end) + +minetest.register_globalstep(function(dtime) + local players = minetest.get_connected_players() + for i, player in pairs(players) do + update_wieldview_entity(player) + end +end) diff --git a/mods/PLAYER/mcl_wieldview/mod.conf b/mods/PLAYER/mcl_wieldview/mod.conf index 4b3097876..7ed41eeb4 100644 --- a/mods/PLAYER/mcl_wieldview/mod.conf +++ b/mods/PLAYER/mcl_wieldview/mod.conf @@ -1,4 +1,4 @@ name = mcl_wieldview author = stujones11 description = Makes hand wielded items visible to other players. -depends = mcl_player +depends = mcl_armor, mcl_playerplus