mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-11-24 11:53:46 +01:00
Merge pull request 'Update from master' (#1) from MineClone2/MineClone2:master into master
Reviewed-on: https://git.minetest.land/FaceDeer/MineClone2/pulls/1
This commit is contained in:
commit
be36022249
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
local vv = self.object:get_velocity()
|
||||
if vv then
|
||||
self.object:set_velocity({
|
||||
x = (sin(yaw) * -v) + c_x,
|
||||
y = self.object:get_velocity().y,
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
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,10 +335,6 @@ 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()
|
||||
@ -325,11 +344,15 @@ mcl_mobs:register_mob("mobs_mc:enderman", {
|
||||
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(
|
||||
|
@ -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
|
||||
|
@ -65,3 +65,4 @@ Nitwit=
|
||||
Cod=
|
||||
Salmon=
|
||||
Dolphin=
|
||||
Pillager=
|
||||
|
BIN
mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.b3d
Normal file
BIN
mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.b3d
Normal file
Binary file not shown.
BIN
mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.blend
Normal file
BIN
mods/ENTITIES/mobs_mc/models/mobs_mc_pillager.blend
Normal file
Binary file not shown.
@ -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
|
||||
|
122
mods/ENTITIES/mobs_mc/pillager.lua
Normal file
122
mods/ENTITIES/mobs_mc/pillager.lua
Normal file
@ -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)
|
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt1.ogg
Normal file
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt1.ogg
Normal file
Binary file not shown.
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt2.ogg
Normal file
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_grunt2.ogg
Normal file
Binary file not shown.
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow1.ogg
Normal file
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow1.ogg
Normal file
Binary file not shown.
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow2.ogg
Normal file
BIN
mods/ENTITIES/mobs_mc/sounds/mobs_mc_pillager_ow2.ogg
Normal file
Binary file not shown.
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png
Normal file
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_pillager.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png
Normal file
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_spawn_icon_pillager.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 477 B |
@ -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,
|
||||
|
@ -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,6 +169,7 @@ 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",
|
||||
}},
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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,
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 359 B |
@ -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
|
||||
})
|
||||
|
10
mods/ITEMS/mcl_grindstone/locale/template.txt
Normal file
10
mods/ITEMS/mcl_grindstone/locale/template.txt
Normal file
@ -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.=
|
@ -1,3 +1,4 @@
|
||||
name = mcl_grindstone
|
||||
author = TheRandomLegoBrick
|
||||
description = Adds a cool looking block for the weaponsmiths jobsite
|
||||
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.
|
||||
|
BIN
mods/ITEMS/mcl_grindstone/textures/gui_crafting_arrow.png
Normal file
BIN
mods/ITEMS/mcl_grindstone/textures/gui_crafting_arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 170 B |
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user