diff --git a/mods/CORE/mcl_util/init.lua b/mods/CORE/mcl_util/init.lua index 32c3b0dee..50e3d61fc 100644 --- a/mods/CORE/mcl_util/init.lua +++ b/mods/CORE/mcl_util/init.lua @@ -485,3 +485,16 @@ function mcl_util.replace_mob(obj, mob) obj:set_yaw(rot) return obj end + +function mcl_util.get_pointed_thing(player) + local pos = vector.offset(player:get_pos(), 0, player:get_properties().eye_height, 0) + local look_dir = vector.multiply(player:get_look_dir(), 5) + local pos2 = vector.add(pos, look_dir) + local ray = minetest.raycast(pos, pos2, false, true) + + if ray then + for pointed_thing in ray do + return pointed_thing + end + end +end diff --git a/mods/ENTITIES/mobs_mc/1_items_default.lua b/mods/ENTITIES/mobs_mc/1_items_default.lua index c8ac421cc..d792af0a2 100644 --- a/mods/ENTITIES/mobs_mc/1_items_default.lua +++ b/mods/ENTITIES/mobs_mc/1_items_default.lua @@ -525,7 +525,7 @@ if c("totem") then inventory_image = "mcl_totems_totem.png", wield_image = "mcl_totems_totem.png", stack_max = 1, - groups = {combat_item=1}, + groups = {combat_item = 1, offhand_item = 1}, }) end diff --git a/mods/ENVIRONMENT/mcl_weather/rain.lua b/mods/ENVIRONMENT/mcl_weather/rain.lua index 220b61006..191062bcd 100644 --- a/mods/ENVIRONMENT/mcl_weather/rain.lua +++ b/mods/ENVIRONMENT/mcl_weather/rain.lua @@ -1,5 +1,5 @@ -local PARTICLES_COUNT_RAIN = 30 -local PARTICLES_COUNT_THUNDER = 45 +local PARTICLES_COUNT_RAIN = 100 +local PARTICLES_COUNT_THUNDER = 300 local get_connected_players = minetest.get_connected_players @@ -19,6 +19,45 @@ mcl_weather.rain = { init_done = false, } +local update_sound={} +local vel=math.random(0,3) +local falling_speed=math.random(10,15) +local size = math.random(1,3) +local psdef= { + amount = mcl_weather.rain.particles_count, + time=0, + minpos = vector.new(-6,3,-6), + maxpos = vector.new(6,15,6), + minvel = vector.new(-vel,-falling_speed,-vel), + maxvel = math.random(vel,-falling_speed+vel,vel), + minacc = vector.new(0,0,0), + maxacc = vector.new(0,-0.4,0), + minexptime = 0.5, + maxexptime = 2, + minsize = size, + maxsize= size*2, + collisiondetection = true, + collision_removal = true, + vertical = true, +} +local psdef_backsplash= { + amount = 10, + time=0, + minpos = vector.new(-3,-1,-3), + maxpos = vector.new(3,0,3), + minvel = vector.new(-vel,falling_speed*2,-vel), + maxvel = math.random(vel,falling_speed*2+vel,vel), + minacc = vector.new(0,0,0), + maxacc = vector.new(0,0,0), + minexptime = 0.1, + maxexptime = 0.2, + minsize = size*0.1, + maxsize= size*0.5, + collisiondetection = true, + collision_removal = true, + vertical = true, +} +local textures = {"weather_pack_rain_raindrop_1.png", "weather_pack_rain_raindrop_2.png", "weather_pack_rain_raindrop_1.png"} function mcl_weather.rain.sound_handler(player) return minetest.sound_play("weather_rain", { @@ -44,42 +83,18 @@ function mcl_weather.rain.set_sky_box() end end --- creating manually parctiles instead of particles spawner because of easier to control --- spawn position. +-- no no no NO NO f*.. no. no manual particle creatin' PLS!! this sends EVERY particle over the net. function mcl_weather.rain.add_rain_particles(player) - mcl_weather.rain.last_rp_count = 0 - for i=mcl_weather.rain.particles_count, 1,-1 do - local random_pos_x, random_pos_y, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player) - if mcl_weather.is_outdoor({x=random_pos_x, y=random_pos_y, z=random_pos_z}) then - mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1 - minetest.add_particle({ - pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, - velocity = {x=0, y=-10, z=0}, - acceleration = {x=0, y=-30, z=0}, - expirationtime = 1.0, - size = math.random(0.5, 3), - collisiondetection = true, - collision_removal = true, - vertical = true, - texture = mcl_weather.rain.get_texture(), - playername = player:get_player_name() - }) - end + mcl_weather.rain.last_rp_count = mcl_weather.rain.particles_count + for k,v in pairs(textures) do + psdef.texture=v + mcl_weather.add_spawner_player(player,"rain"..k,psdef) end -end - --- Simple random texture getter -function mcl_weather.rain.get_texture() - local texture_name - local random_number = math.random() - if random_number > 0.33 then - texture_name = "weather_pack_rain_raindrop_1.png" - elseif random_number > 0.66 then - texture_name = "weather_pack_rain_raindrop_2.png" - else - texture_name = "weather_pack_rain_raindrop_3.png" + psdef_backsplash.texture=textures[math.random(1,#textures)] + local l=mcl_weather.add_spawner_player(player,"rainbacksplash",psdef_backsplash) + if l then + update_sound[player:get_player_name()]=true end - return texture_name; end -- register player for rain weather. @@ -89,6 +104,7 @@ function mcl_weather.rain.add_player(player) local player_meta = {} player_meta.origin_sky = {player:get_sky()} mcl_weather.players[player:get_player_name()] = player_meta + update_sound[player:get_player_name()]=true end end @@ -99,6 +115,7 @@ function mcl_weather.rain.remove_player(player) if player_meta and player_meta.origin_sky then player:set_clouds({color="#FFF0F0E5"}) mcl_weather.players[player:get_player_name()] = nil + update_sound[player:get_player_name()]=true end end @@ -119,6 +136,7 @@ end) -- have few seconds delay before each check to avoid on/off sound too often -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance. function mcl_weather.rain.update_sound(player) + if not update_sound[player:get_player_name()] then return end local player_meta = mcl_weather.players[player:get_player_name()] if player_meta then if player_meta.sound_updated and player_meta.sound_updated + 5 > minetest.get_gametime() then @@ -136,6 +154,7 @@ function mcl_weather.rain.update_sound(player) player_meta.sound_updated = minetest.get_gametime() end + update_sound[player:get_player_name()]=false end -- rain sound removed from player. @@ -158,7 +177,8 @@ function mcl_weather.rain.clear() for _, player in pairs(get_connected_players()) do mcl_weather.rain.remove_sound(player) mcl_weather.rain.remove_player(player) - end + mcl_weather.remove_spawners_player(player) + end end minetest.register_globalstep(function(dtime) @@ -177,8 +197,10 @@ function mcl_weather.rain.make_weather() end for _, player in pairs(get_connected_players()) do - if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then + local pos=player:get_pos() + if mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(pos) or not mcl_weather.is_outdoor(pos) then mcl_weather.rain.remove_sound(player) + mcl_weather.remove_spawners_player(player) return false end mcl_weather.rain.add_player(player) @@ -190,8 +212,12 @@ end -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops function mcl_weather.rain.set_particles_mode(mode) if mode == "thunder" then + psdef.amount=PARTICLES_COUNT_THUNDER + psdef_backsplash.amount=PARTICLES_COUNT_THUNDER mcl_weather.rain.particles_count = PARTICLES_COUNT_THUNDER else + psdef.amount=PARTICLES_COUNT_RAIN + psdef_backsplash.amount=PARTICLES_COUNT_RAIN mcl_weather.rain.particles_count = PARTICLES_COUNT_RAIN end end diff --git a/mods/ENVIRONMENT/mcl_weather/snow.lua b/mods/ENVIRONMENT/mcl_weather/snow.lua index 9f89a3a0a..b60283127 100644 --- a/mods/ENVIRONMENT/mcl_weather/snow.lua +++ b/mods/ENVIRONMENT/mcl_weather/snow.lua @@ -5,30 +5,25 @@ mcl_weather.snow = {} mcl_weather.snow.particles_count = 15 mcl_weather.snow.init_done = false --- calculates coordinates and draw particles for snow weather -function mcl_weather.snow.add_snow_particles(player) - mcl_weather.rain.last_rp_count = 0 - for i=mcl_weather.snow.particles_count, 1,-1 do - local random_pos_x, _, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player) - local random_pos_y = math.random() + math.random(player:get_pos().y - 1, player:get_pos().y + 7) - if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then - mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1 - minetest.add_particle({ - pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, - velocity = {x = math.random(-100,100)*0.001, y = math.random(-300,-100)*0.004, z = math.random(-100,100)*0.001}, - acceleration = {x = 0, y=0, z = 0}, - expirationtime = 8.0, - size = 1, - collisiondetection = true, - collision_removal = true, - object_collision = false, - vertical = false, - texture = mcl_weather.snow.get_texture(), - playername = player:get_player_name() - }) - end - end -end +local psdef= { + amount = 99, + time = 0, --stay on til we turn it off + minpos = vector.new(-15,-5,-15), + maxpos =vector.new(15,10,15), + minvel = vector.new(0,-1,0), + maxvel = vector.new(0,-4,0), + minacc = vector.new(0,-1,0), + maxacc = vector.new(0,-4,0), + minexptime = 1, + maxexptime = 1, + minsize = 0.5, + maxsize = 5, + collisiondetection = true, + collision_removal = true, + object_collision = true, + vertical = true, + glow = 1 +} function mcl_weather.snow.set_sky_box() mcl_weather.skycolor.add_layer( @@ -48,6 +43,7 @@ end function mcl_weather.snow.clear() mcl_weather.skycolor.remove_layer("weather-pack-snow-sky") mcl_weather.snow.init_done = false + mcl_weather.remove_all_spawners() end -- Simple random texture getter @@ -74,10 +70,14 @@ minetest.register_globalstep(function(dtime) end for _, player in pairs(get_connected_players()) do - if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos())) then + if (mcl_weather.is_underwater(player) or not mcl_worlds.has_weather(player:get_pos()) or not mcl_weather.is_outdoor(player:get_pos())) then + mcl_weather.remove_spawners_player(player) return false end - mcl_weather.snow.add_snow_particles(player) + for i=1,2 do + psdef.texture="weather_pack_snow_snowflake"..i..".png" + mcl_weather.add_spawner_player(player,"snow"..i,psdef) + end end end) diff --git a/mods/ENVIRONMENT/mcl_weather/weather_core.lua b/mods/ENVIRONMENT/mcl_weather/weather_core.lua index 34f69406d..f7316bcfb 100644 --- a/mods/ENVIRONMENT/mcl_weather/weather_core.lua +++ b/mods/ENVIRONMENT/mcl_weather/weather_core.lua @@ -47,6 +47,35 @@ local function save_weather() end minetest.register_on_shutdown(save_weather) +local particlespawners={} +function mcl_weather.add_spawner_player(pl,id,ps) + local name=pl:get_player_name() + if not particlespawners[name] then + particlespawners[name] = {} + end + if not particlespawners[name][id] then + ps.playername =name + ps.attached = pl + particlespawners[name][id]=minetest.add_particlespawner(ps) + return particlespawners[name][id] + end +end +function mcl_weather.remove_spawners_player(pl) + local name=pl:get_player_name() + if not particlespawners[name] then return end + for k,v in pairs(particlespawners[name]) do + minetest.delete_particlespawner(v) + end + particlespawners[name] = nil + return true +end + +function mcl_weather.remove_all_spawners() + for k,v in pairs(minetest.get_connected_players()) do + mcl_weather.remove_spawners_player(v) + end +end + function mcl_weather.get_rand_end_time(min_duration, max_duration) local r if min_duration and max_duration then @@ -92,36 +121,6 @@ function mcl_weather.is_underwater(player) return false end --- trying to locate position for particles by player look direction for performance reason. --- it is costly to generate many particles around player so goal is focus mainly on front view. -function mcl_weather.get_random_pos_by_player_look_dir(player) - local look_dir = player:get_look_dir() - local player_pos = player:get_pos() - - local random_pos_x, random_pos_y, random_pos_z - - if look_dir.x > 0 then - if look_dir.z > 0 then - random_pos_x = math.random() + math.random(player_pos.x - 2.5, player_pos.x + 5) - random_pos_z = math.random() + math.random(player_pos.z - 2.5, player_pos.z + 5) - else - random_pos_x = math.random() + math.random(player_pos.x - 2.5, player_pos.x + 5) - random_pos_z = math.random() + math.random(player_pos.z - 5, player_pos.z + 2.5) - end - else - if look_dir.z > 0 then - random_pos_x = math.random() + math.random(player_pos.x - 5, player_pos.x + 2.5) - random_pos_z = math.random() + math.random(player_pos.z - 2.5, player_pos.z + 5) - else - random_pos_x = math.random() + math.random(player_pos.x - 5, player_pos.x + 2.5) - random_pos_z = math.random() + math.random(player_pos.z - 5, player_pos.z + 2.5) - end - end - - random_pos_y = math.random() + math.random(player_pos.y + 10, player_pos.y + 15) - return random_pos_x, random_pos_y, random_pos_z -end - local t, wci = 0, mcl_weather.check_interval minetest.register_globalstep(function(dtime) diff --git a/mods/HUD/mcl_inventory/creative.lua b/mods/HUD/mcl_inventory/creative.lua index 67a04b567..f2bd8076a 100644 --- a/mods/HUD/mcl_inventory/creative.lua +++ b/mods/HUD/mcl_inventory/creative.lua @@ -362,6 +362,10 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, if inv:get_stack("armor", 5):is_empty() then armor_slot_imgs = armor_slot_imgs .. "image[5.5,2.75;1,1;mcl_inventory_empty_armor_slot_boots.png]" end + + if inv:get_stack("offhand", 1):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[1.5,2.025;1,1;mcl_inventory_empty_armor_slot_shield.png]" + end local stack_size = get_stack_size(player) @@ -377,9 +381,13 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size, mcl_formspec.get_itemslot_bg(2.5,2.75,1,1).. mcl_formspec.get_itemslot_bg(5.5,1.3,1,1).. mcl_formspec.get_itemslot_bg(5.5,2.75,1,1).. + "list[current_player;offhand;1.5,2.025;1,1]".. + mcl_formspec.get_itemslot_bg(1.5,2.025,1,1).. + armor_slot_imgs.. -- player preview player_preview.. + -- crafting guide button "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]".. "tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]".. diff --git a/mods/HUD/mcl_inventory/init.lua b/mods/HUD/mcl_inventory/init.lua index 1785ed91f..f59476965 100644 --- a/mods/HUD/mcl_inventory/init.lua +++ b/mods/HUD/mcl_inventory/init.lua @@ -76,6 +76,10 @@ local function set_inventory(player, armor_change_only) end end + if inv:get_stack("offhand", 1):is_empty() then + armor_slot_imgs = armor_slot_imgs .. "image[3,2;1,1;mcl_inventory_empty_armor_slot_shield.png]" + end + local form = "size[9,8.75]".. "background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]".. player_preview.. @@ -88,6 +92,8 @@ local function set_inventory(player, armor_change_only) mcl_formspec.get_itemslot_bg(0,1,1,1).. mcl_formspec.get_itemslot_bg(0,2,1,1).. mcl_formspec.get_itemslot_bg(0,3,1,1).. + "list[current_player;offhand;3,2;1,1]".. + mcl_formspec.get_itemslot_bg(3,2,1,1).. armor_slot_imgs.. -- craft and inventory "label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))).."]".. @@ -112,6 +118,7 @@ local function set_inventory(player, armor_change_only) -- achievements button "image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]".. "tooltip[__mcl_achievements;"..F(S("Achievements")).."]".. + -- for shortcuts "listring[current_player;main]".. "listring[current_player;armor]".. @@ -148,8 +155,11 @@ end) minetest.register_on_joinplayer(function(player) --init inventory - player:get_inventory():set_width("main", 9) - player:get_inventory():set_size("main", 36) + local inv = player:get_inventory() + inv:set_width("main", 9) + inv:set_size("main", 36) + inv:set_size("offhand", 1) + --set hotbar size player:hud_set_hotbar_itemcount(9) diff --git a/mods/HUD/mcl_offhand/init.lua b/mods/HUD/mcl_offhand/init.lua new file mode 100644 index 000000000..b0fc223ec --- /dev/null +++ b/mods/HUD/mcl_offhand/init.lua @@ -0,0 +1,171 @@ +local minetest, math = minetest, math +mcl_offhand = {} + +local max_offhand_px = 128 +-- only supports up to 128px textures + +function mcl_offhand.get_offhand(player) + return player:get_inventory():get_stack("offhand", 1) +end + +local function offhand_get_wear(player) + return mcl_offhand.get_offhand(player):get_wear() +end + +local function offhand_get_count(player) + return mcl_offhand.get_offhand(player):get_count() +end + +minetest.register_on_joinplayer(function(player, last_login) + mcl_offhand[player] = { + hud = {}, + last_wear = offhand_get_wear(player), + last_count = offhand_get_count(player), + } +end) + +local function remove_hud(player, hud) + local offhand_hud = mcl_offhand[player].hud[hud] + if offhand_hud then + player:hud_remove(offhand_hud) + mcl_offhand[player].hud[hud] = nil + end +end + +function rgb_to_hex(r, g, b) + return string.format("%02x%02x%02x", r, g, b) +end + +local function update_wear_bar(player, itemstack) + local wear_bar_percent = (65535 - offhand_get_wear(player)) / 65535 + + local color = {255, 255, 255} + local wear = itemstack:get_wear() / 65535; + local wear_i = math.min(math.floor(wear * 600), 511); + wear_i = math.min(wear_i + 10, 511); + if wear_i <= 255 then + color = {wear_i, 255, 0} + else + color = {255, 511 - wear_i, 0} + end + local wear_bar = mcl_offhand[player].hud.wear_bar + player:hud_change(wear_bar, "text", "mcl_wear_bar.png^[colorize:#" .. rgb_to_hex(color[1], color[2], color[3])) + player:hud_change(wear_bar, "scale", {x = 40 * wear_bar_percent, y = 3}) + player:hud_change(wear_bar, "offset", {x = -320 - (20 - player:hud_get(wear_bar).scale.x / 2), y = -13}) +end + +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + local itemstack = mcl_offhand.get_offhand(player) + local offhand_item = itemstack:get_name() + local offhand_hud = mcl_offhand[player].hud + if offhand_item ~= "" then + local item_texture = minetest.registered_items[offhand_item].inventory_image .. "^[resize:" .. max_offhand_px .. "x" .. max_offhand_px + local position = {x = 0.5, y = 1} + local offset = {x = -320, y = -32} + + if not offhand_hud.slot then + offhand_hud.slot = player:hud_add({ + hud_elem_type = "image", + position = position, + offset = offset, + scale = {x = 2.75, y = 2.75}, + text = "mcl_offhand_slot.png", + z_index = 0, + }) + end + if not offhand_hud.item then + offhand_hud.item = player:hud_add({ + hud_elem_type = "image", + position = position, + offset = offset, + scale = {x = 0.4, y = 0.4}, + text = item_texture, + z_index = 1, + }) + else + player:hud_change(offhand_hud.item, "text", item_texture) + end + if not offhand_hud.wear_bar_bg and minetest.registered_tools[offhand_item] then + if offhand_get_wear(player) > 0 then + local texture = "mcl_wear_bar.png^[colorize:#000000" + offhand_hud.wear_bar_bg = player:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 1}, + offset = {x = -320, y = -13}, + scale = {x = 40, y = 3}, + text = texture, + z_index = 2, + }) + offhand_hud.wear_bar = player:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 1}, + offset = {x = -320, y = -13}, + scale = {x = 10, y = 3}, + text = texture, + z_index = 3, + }) + update_wear_bar(player, itemstack) + end + end + + if not offhand_hud.item_count and offhand_get_count(player) > 1 then + offhand_hud.item_count = player:hud_add({ + hud_elem_type = "text", + position = {x = 0.5, y = 1}, + offset = {x = -298, y = -18}, + scale = {x = 1, y = 1}, + alignment = {x = -1, y = 0}, + text = offhand_get_count(player), + z_index = 4, + number = 0xFFFFFF, + }) + end + + if offhand_hud.wear_bar then + if offhand_hud.last_wear ~= offhand_get_wear(player) then + update_wear_bar(player, itemstack) + offhand_hud.last_wear = offhand_get_wear(player) + end + if offhand_get_wear(player) <= 0 or not minetest.registered_tools[offhand_item] then + remove_hud(player, "wear_bar_bg") + remove_hud(player, "wear_bar") + end + end + + if offhand_hud.item_count then + if offhand_hud.last_count ~= offhand_get_count(player) then + player:hud_change(offhand_hud.item_count, "text", offhand_get_count(player)) + offhand_hud.last_count = offhand_get_count(player) + end + if offhand_get_count(player) <= 1 then + remove_hud(player, "item_count") + end + end + + elseif offhand_hud.slot then + for index, _ in pairs(mcl_offhand[player].hud) do + remove_hud(player, index) + end + end + end +end) + +minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info) + if action == "move" and inventory_info.to_list == "offhand" then + local itemstack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index) + if not (minetest.get_item_group(itemstack:get_name(), "offhand_item") > 0) then + return 0 + else + return itemstack:get_stack_max() + end + end +end) + +minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info) + local from_offhand = inventory_info.from_list == "offhand" + local to_offhand = inventory_info.to_list == "offhand" + if action == "move" and from_offhand or to_offhand then + mcl_inventory.update_inventory_formspec(player) + end +end) diff --git a/mods/HUD/mcl_offhand/mod.conf b/mods/HUD/mcl_offhand/mod.conf new file mode 100644 index 000000000..f0260f35c --- /dev/null +++ b/mods/HUD/mcl_offhand/mod.conf @@ -0,0 +1,3 @@ +name = mcl_offhand +author = NO11 +depends = mcl_inventory diff --git a/mods/HUD/mcl_offhand/textures/mcl_offhand_slot.png b/mods/HUD/mcl_offhand/textures/mcl_offhand_slot.png new file mode 100644 index 000000000..69ceb5973 Binary files /dev/null and b/mods/HUD/mcl_offhand/textures/mcl_offhand_slot.png differ diff --git a/mods/HUD/mcl_offhand/textures/mcl_wear_bar.png b/mods/HUD/mcl_offhand/textures/mcl_wear_bar.png new file mode 100644 index 000000000..6fee6bba6 Binary files /dev/null and b/mods/HUD/mcl_offhand/textures/mcl_wear_bar.png differ diff --git a/mods/ITEMS/mcl_banners/init.lua b/mods/ITEMS/mcl_banners/init.lua index a396caf7d..cc0e02e66 100644 --- a/mods/ITEMS/mcl_banners/init.lua +++ b/mods/ITEMS/mcl_banners/init.lua @@ -88,6 +88,10 @@ for k,v in pairs(mcl_banners.colors) do colors_reverse["mcl_banners:banner_item_"..v[1]] = k end +function mcl_banners.color_reverse(itemname) + return colors_reverse[itemname] +end + -- Add pattern/emblazoning crafting recipes dofile(modpath.."/patterncraft.lua") @@ -149,7 +153,7 @@ local function on_destruct_hanging_banner(pos) return on_destruct_banner(pos, true) end -local function make_banner_texture(base_color, layers) +function mcl_banners.make_banner_texture(base_color, layers) local colorize if mcl_banners.colors[base_color] then colorize = mcl_banners.colors[base_color][4] @@ -171,11 +175,11 @@ local function make_banner_texture(base_color, layers) finished_banner = finished_banner .. "^" .. layer end - return { finished_banner } + return finished_banner end - return { base } + return base else - return { "mcl_banners_banner_base.png" } + return "mcl_banners_banner_base.png" end end @@ -192,7 +196,7 @@ local function spawn_banner_entity(pos, hanging, itemstack) local imeta = itemstack:get_meta() local layers_raw = imeta:get_string("layers") local layers = minetest.deserialize(layers_raw) - local colorid = colors_reverse[itemstack:get_name()] + local colorid = mcl_banners.color_reverse(itemstack:get_name()) banner:get_luaentity():_set_textures(colorid, layers) local mname = imeta:get_string("name") if mname and mname ~= "" then @@ -604,7 +608,7 @@ local entity_standing = { visual = "mesh", mesh = "amc_banner.b3d", visual_size = { x=2.499, y=2.499 }, - textures = make_banner_texture(), + textures = {mcl_banners.make_banner_texture()}, pointable = false, _base_color = nil, -- base color of banner @@ -624,7 +628,7 @@ local entity_standing = { self._layers = inp._layers self._name = inp._name self.object:set_properties({ - textures = make_banner_texture(self._base_color, self._layers), + textures = {mcl_banners.make_banner_texture(self._base_color, self._layers)}, }) end -- Make banner slowly swing @@ -635,7 +639,7 @@ local entity_standing = { -- Set the banner textures. This function can be used by external mods. -- Meaning of parameters: -- * self: Lua entity reference to entity. - -- * other parameters: Same meaning as in make_banner_texture + -- * other parameters: Same meaning as in mcl_banners.make_banner_texture _set_textures = function(self, base_color, layers) if base_color then self._base_color = base_color @@ -643,7 +647,7 @@ local entity_standing = { if layers then self._layers = layers end - self.object:set_properties({textures = make_banner_texture(self._base_color, self._layers)}) + self.object:set_properties({textures = {mcl_banners.make_banner_texture(self._base_color, self._layers)}}) end, } minetest.register_entity("mcl_banners:standing_banner", entity_standing) diff --git a/mods/ITEMS/mcl_beds/api.lua b/mods/ITEMS/mcl_beds/api.lua index 85873f3c6..dc4527c78 100644 --- a/mods/ITEMS/mcl_beds/api.lua +++ b/mods/ITEMS/mcl_beds/api.lua @@ -248,7 +248,7 @@ function mcl_beds.register_bed(name, def) paramtype2 = "facedir", is_ground_content = false, -- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks! - groups = {handy = 1, flammable = 3, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1}, + groups = {handy = 1, flammable = -1, bed = 2, dig_by_piston=1, bouncy=33, fall_damage_add_percent=-50, not_in_creative_inventory = 1}, _mcl_hardness = 0.2, _mcl_blast_resistance = 1, sounds = def.sounds or default_sounds, @@ -275,5 +275,3 @@ function mcl_beds.register_bed(name, def) doc.add_entry_alias("nodes", name.."_bottom", "nodes", name.."_top") end - - diff --git a/mods/ITEMS/mcl_bows/arrow.lua b/mods/ITEMS/mcl_bows/arrow.lua index 7529da167..c61dfc26c 100644 --- a/mods/ITEMS/mcl_bows/arrow.lua +++ b/mods/ITEMS/mcl_bows/arrow.lua @@ -74,6 +74,7 @@ local ARROW_ENTITY={ _shooter=nil, -- ObjectRef of player or mob who shot it _is_arrow = true, _in_player = false, + _blocked = false, _viscosity=0, -- Viscosity of node the arrow is currently in _deflection_cooloff=0, -- Cooloff timer after an arrow deflection, to prevent many deflections in quick succession } @@ -82,7 +83,7 @@ local ARROW_ENTITY={ local function spawn_item(self, pos) if not minetest.is_creative_enabled("") then local item = minetest.add_item(pos, "mcl_bows:arrow") - item:set_velocity({x=0, y=0, z=0}) + item:set_velocity(vector.new(0, 0, 0)) item:set_yaw(self.object:get_yaw()) end mcl_burning.extinguish(self.object) @@ -94,12 +95,10 @@ local function damage_particles(pos, is_critical) minetest.add_particlespawner({ amount = 15, time = 0.1, - minpos = {x=pos.x-0.5, y=pos.y-0.5, z=pos.z-0.5}, - maxpos = {x=pos.x+0.5, y=pos.y+0.5, z=pos.z+0.5}, - minvel = {x=-0.1, y=-0.1, z=-0.1}, - maxvel = {x=0.1, y=0.1, z=0.1}, - minacc = {x=0, y=0, z=0}, - maxacc = {x=0, y=0, z=0}, + minpos = vector.offset(pos, -0.5, -0.5, -0.5), + maxpos = vector.offset(pos, 0.5, 0.5, 0.5), + minvel = vector.new(-0.1, -0.1, -0.1), + maxvel = vector.new(0.1, 0.1, 0.1), minexptime = 1, maxexptime = 2, minsize = 1.5, @@ -248,50 +247,59 @@ function ARROW_ENTITY.on_step(self, dtime) -- Punch target object but avoid hurting enderman. if not lua or lua.name ~= "mobs_mc:enderman" then - if self._in_player == false then + if not self._in_player then damage_particles(self.object:get_pos(), self._is_critical) end if mcl_burning.is_burning(self.object) then mcl_burning.set_on_fire(obj, 5) end - if self._in_player == false then + if not self._in_player and not self._blocked then obj:punch(self.object, 1.0, { full_punch_interval=1.0, damage_groups={fleshy=self._damage}, }, self.object:get_velocity()) if obj:is_player() then - local placement - self._placement = math.random(1, 2) - if self._placement == 1 then - placement = "front" + if not mcl_shields.is_blocking(obj) then + local placement + self._placement = math.random(1, 2) + if self._placement == 1 then + placement = "front" + else + placement = "back" + end + self._in_player = true + if self._placement == 2 then + self._rotation_station = 90 + else + self._rotation_station = -90 + end + self._y_position = random_arrow_positions("y", placement) + self._x_position = random_arrow_positions("x", placement) + if self._y_position > 6 and self._x_position < 2 and self._x_position > -2 then + self._attach_parent = "Head" + self._y_position = self._y_position - 6 + elseif self._x_position > 2 then + self._attach_parent = "Arm_Right" + self._y_position = self._y_position - 3 + self._x_position = self._x_position - 2 + elseif self._x_position < -2 then + self._attach_parent = "Arm_Left" + self._y_position = self._y_position - 3 + self._x_position = self._x_position + 2 + else + self._attach_parent = "Body" + end + self._z_rotation = math.random(-30, 30) + self._y_rotation = math.random( -30, 30) + self.object:set_attach( + obj, self._attach_parent, + vector.new(self._x_position, self._y_position, random_arrow_positions("z", placement)), + vector.new(0, self._rotation_station + self._y_rotation, self._z_rotation) + ) else - placement = "back" + self._blocked = true + self.object:set_velocity(vector.multiply(self.object:get_velocity(), -0.25)) end - self._in_player = true - if self._placement == 2 then - self._rotation_station = 90 - else - self._rotation_station = -90 - end - self._y_position = random_arrow_positions("y", placement) - self._x_position = random_arrow_positions("x", placement) - if self._y_position > 6 and self._x_position < 2 and self._x_position > -2 then - self._attach_parent = "Head" - self._y_position = self._y_position - 6 - elseif self._x_position > 2 then - self._attach_parent = "Arm_Right" - self._y_position = self._y_position - 3 - self._x_position = self._x_position - 2 - elseif self._x_position < -2 then - self._attach_parent = "Arm_Left" - self._y_position = self._y_position - 3 - self._x_position = self._x_position + 2 - else - self._attach_parent = "Body" - end - self._z_rotation = math.random(-30, 30) - self._y_rotation = math.random( -30, 30) - self.object:set_attach(obj, self._attach_parent, {x=self._x_position,y=self._y_position,z=random_arrow_positions("z", placement)}, {x=0,y=self._rotation_station + self._y_rotation,z=self._z_rotation}) minetest.after(150, function() self.object:remove() end) @@ -301,7 +309,7 @@ function ARROW_ENTITY.on_step(self, dtime) if is_player then - if self._shooter and self._shooter:is_player() and self._in_player == false then + if self._shooter and self._shooter:is_player() and not self._in_player and not self._blocked then -- “Ding” sound for hitting another player minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter:get_player_name()}, true) end @@ -318,7 +326,8 @@ function ARROW_ENTITY.on_step(self, dtime) end end end - if self._in_player == false then + if not self._in_player and not self._blocked then + minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true) end end @@ -344,9 +353,9 @@ function ARROW_ENTITY.on_step(self, dtime) local dir if math.abs(vel.y) < 0.00001 then if self._lastpos.y < pos.y then - dir = {x=0, y=1, z=0} + dir = vector.new(0, 1, 0) else - dir = {x=0, y=-1, z=0} + dir = vector.new(0, -1, 0) end else dir = minetest.facedir_to_dir(minetest.dir_to_facedir(minetest.yaw_to_dir(self.object:get_yaw()-YAW_OFFSET))) @@ -374,8 +383,8 @@ function ARROW_ENTITY.on_step(self, dtime) self._stucktimer = 0 self._stuckrechecktimer = 0 - self.object:set_velocity({x=0, y=0, z=0}) - self.object:set_acceleration({x=0, y=0, z=0}) + self.object:set_velocity(vector.new(0, 0, 0)) + self.object:set_acceleration(vector.new(0, 0, 0)) minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true) @@ -420,7 +429,7 @@ function ARROW_ENTITY.on_step(self, dtime) end -- Update internal variable - self._lastpos={x=pos.x, y=pos.y, z=pos.z} + self._lastpos = pos end -- Force recheck of stuck arrows when punched. diff --git a/mods/ITEMS/mcl_bows/crossbow.lua b/mods/ITEMS/mcl_bows/crossbow.lua index 3c92a4c92..49a434c5b 100644 --- a/mods/ITEMS/mcl_bows/crossbow.lua +++ b/mods/ITEMS/mcl_bows/crossbow.lua @@ -116,7 +116,7 @@ end -- Bow item, uncharged state minetest.register_tool("mcl_bows:crossbow", { - description = S("Corssbow"), + description = S("Crossbow"), _tt_help = S("Launches arrows"), _doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes.").."\n".. S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."), @@ -151,11 +151,11 @@ S("The speed and damage of the arrow increases the longer you charge. The regula }) minetest.register_tool("mcl_bows:crossbow_loaded", { - description = S("Corssbow"), + description = S("Crossbow"), _tt_help = S("Launches arrows"), - _doc_items_longdesc = S("Corssbow are ranged weapons to shoot arrows at your foes.").."\n".. + _doc_items_longdesc = S("Crossbow is a ranged weapon to shoot arrows at your foes.").."\n".. S("The speed and damage of the arrow increases the longer you charge. The regular damage of the arrow is between 1 and 9. At full charge, there's also a 20% of a critical hit, dealing 10 damage instead."), - _doc_items_usagehelp = S("To use the corssbow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to load an arrow into the chamber, then to shoot press left mouse."), + _doc_items_usagehelp = S("To use the crossbow, you first need to have at least one arrow anywhere in your inventory (unless in Creative Mode). Hold down the right mouse button to charge, release to load an arrow into the chamber, then to shoot press left mouse."), _doc_items_durability = BOW_DURABILITY, inventory_image = "mcl_bows_crossbow_3.png", wield_scale = mcl_vars.tool_wield_scale, diff --git a/mods/ITEMS/mcl_bows/mod.conf b/mods/ITEMS/mcl_bows/mod.conf index 79ae42436..a23eb72ab 100644 --- a/mods/ITEMS/mcl_bows/mod.conf +++ b/mods/ITEMS/mcl_bows/mod.conf @@ -1,6 +1,6 @@ name = mcl_bows author = Arcelmi description = This mod adds bows and arrows for MineClone 2. -depends = controls, mcl_particles, mcl_enchanting, mcl_init +depends = controls, mcl_particles, mcl_enchanting, mcl_init, mcl_shields optional_depends = awards, mcl_achievements, mcl_core, mcl_mobitems, playerphysics, doc, doc_identifier, mesecons_button diff --git a/mods/ITEMS/mcl_enchanting/enchantments.lua b/mods/ITEMS/mcl_enchanting/enchantments.lua index e876baf31..4edd79ec9 100644 --- a/mods/ITEMS/mcl_enchanting/enchantments.lua +++ b/mods/ITEMS/mcl_enchanting/enchantments.lua @@ -388,6 +388,7 @@ mcl_experience.register_on_add_xp(function(player, xp) {list = "armor", index = 3}, {list = "armor", index = 4}, {list = "armor", index = 5}, + {list = "offhand", index = 1}, } local final_candidates = {} diff --git a/mods/ITEMS/mcl_fire/init.lua b/mods/ITEMS/mcl_fire/init.lua index 9f1337a5d..ee06c6e20 100644 --- a/mods/ITEMS/mcl_fire/init.lua +++ b/mods/ITEMS/mcl_fire/init.lua @@ -37,7 +37,7 @@ local lava_fire= { x = 1, y = 1, z = 0}, { x = 1, y = 1, z = 1} } -local alldirs= +local adjacents = { { x =-1, y = 0, z = 0}, { x = 1, y = 0, z = 0}, @@ -87,7 +87,7 @@ else end local function fire_timer(pos) - minetest.get_node_timer(pos):start(math.random(3, 7)) + minetest.get_node_timer(pos):start(math.random(15, 45)) end local function spawn_fire(pos, age) @@ -95,6 +95,23 @@ local function spawn_fire(pos, age) minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z}) end +local function shuffle_adjacents() + for i = #adjacents, 1, -1 do + local r = math.random(i) + adjacents[i], adjacents[r] = adjacents[r], adjacents[i] + end +end + +local function has_flammable(pos) + for k,v in pairs(adjacents) do + local p=vector.add(pos,v) + local n=minetest.get_node_or_nil(p) + if n and minetest.get_item_group(n.name, "flammable") ~= 0 then + return p + end + end +end + minetest.register_node("mcl_fire:fire", { description = S("Fire"), _doc_items_longdesc = fire_help, @@ -125,80 +142,12 @@ minetest.register_node("mcl_fire:fire", { end end, on_timer = function(pos) - local node = get_node(pos) - -- Age is a number from 0 to 15 and is increased every timer step. - -- "old" fire is more likely to be extinguished - local age = node.param2 - local flammables = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"}) - local below = get_node({x=pos.x, y=pos.z-1, z=pos.z}) - local below_is_flammable = get_item_group(below.name, "flammable") > 0 - -- Extinguish fire - if (not fire_enabled) and (math.random(1,3) == 1) then - remove_node(pos) + local p=has_flammable(pos) + if not p or minetest.get_item_group(minetest.get_node(p).name, "flammable") == -1 then + minetest.remove_node(pos) return end - if age == 15 and not below_is_flammable then - remove_node(pos) - return - elseif age > 3 and #flammables == 0 and not below_is_flammable and math.random(1,4) == 1 then - remove_node(pos) - return - end - local age_add = 1 - -- If fire spread is disabled, we have to skip the "destructive" code - if (not fire_enabled) then - if age + age_add <= 15 then - node.param2 = age + age_add - set_node(pos, node) - end - -- Restart timer - fire_timer(pos) - return - end - -- Spawn fire to nearby flammable nodes - local is_next_to_flammable = find_node_near(pos, 2, {"group:flammable"}) ~= nil - if is_next_to_flammable and math.random(1,2) == 1 then - -- The fire we spawn copies the age of this fire. - -- This prevents fire from spreading infinitely far as the fire fire dies off - -- quicker the further it has spreaded. - local age_next = math.min(15, age + math.random(0, 1)) - -- Select random type of fire spread - local burntype = math.random(1,2) - if burntype == 1 then - -- Spawn fire in air - local nodes = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"}) - while #nodes > 0 do - local r = math.random(1, #nodes) - if find_node_near(nodes[r], 1, {"group:flammable"}) then - spawn_fire(nodes[r], age_next) - break - else - table.remove(nodes, r) - end - end - else - -- Burn flammable block - local nodes = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"group:flammable"}) - if #nodes > 0 then - local r = math.random(1, #nodes) - local nn = get_node(nodes[r]).name - local ndef = minetest.registered_nodes[nn] - local fgroup = get_item_group(nn, "flammable") - if ndef and ndef._on_burn then - ndef._on_burn(nodes[r]) - elseif fgroup ~= -1 then - spawn_fire(nodes[r], age_next) - end - end - end - end - -- Regular age increase - if age + age_add <= 15 then - node.param2 = age + age_add - set_node(pos, node) - end - -- Restart timer - fire_timer(pos) + return true --restart timer end, drop = "", sounds = {}, @@ -254,29 +203,8 @@ minetest.register_node("mcl_fire:eternal_fire", { minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true) end end, - on_timer = function(pos) - if fire_enabled then - local airs = find_nodes_in_area({x=pos.x-1, y=pos.y-1, z=pos.z-1}, {x=pos.x+1, y=pos.y+4, z=pos.z+1}, {"air"}) - while #airs > 0 do - local r = math.random(1, #airs) - if find_node_near(airs[r], 1, {"group:flammable"}) then - local node = get_node(airs[r]) - local age = node.param2 - local age_next = math.min(15, age + math.random(0, 1)) - spawn_fire(airs[r], age_next) - break - else - table.remove(airs, r) - end - end - end - -- Restart timer - fire_timer(pos) - end, - -- Start burning timer and light Nether portal (if possible) + -- light Nether portal (if possible) on_construct = function(pos) - fire_timer(pos) - if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time mcl_portals.light_nether_portal(pos) end @@ -421,21 +349,39 @@ minetest.register_abm({ end, }) +--- Fire spread logic --- Enable the following ABMs according to 'enable fire' setting +-- A fire that is not adjacent to any flammable block does not spread, even to another flammable block within the normal range. +-- A fire block can turn any air block that is adjacent to a flammable block into a fire block. This can happen at a distance of up to one block downward, one block sideways (including diagonals), and four blocks upward of the original fire block (not the block the fire is on/next to). +-- Fire spreads from a still lava block similarly: any air block one above and up to one block sideways (including diagonals) or two above and two blocks sideways (including diagonals) that is adjacent to a flammable block may be turned into a fire block. +-- https://minecraft.fandom.com/wiki/Fire#Spread -local function has_flammable(pos) - local npos, node - for n, v in ipairs(alldirs) do - npos = vector.add(pos, v) - node = get_node_or_nil(npos) - if node and node.name and get_item_group(node.name, "flammable") ~= 0 then - return npos - end +local function check_aircube(p1,p2) + local nds=minetest.find_nodes_in_area(p1,p2,{"air"}) + for k,v in pairs(nds) do + if has_flammable(v) then return v end end return false end +local function get_ignitable(pos) + return check_aircube(vector.add(pos,vector.new(-1,-1,-1)),vector.add(pos,vector.new(1,4,1))) +end + +local function get_ignitable_by_lava(pos) + return check_aircube(vector.add(pos,vector.new(-1,1,-1)),vector.add(pos,vector.new(1,1,1))) or check_aircube(vector.add(pos,vector.new(-2,2,-2)),vector.add(pos,vector.new(2,2,2))) or nil +end + +local function add_fire_particle(pos,f) + minetest.add_particle({ + pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), + velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z}, + expirationtime=1, size=1, collisiondetection=false, + glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" + }) +end + +-- Enable the following ABMs according to 'enable fire' setting if not fire_enabled then -- Occasionally remove fire if fire disabled @@ -451,62 +397,70 @@ if not fire_enabled then else -- Fire enabled + minetest.register_abm({ + label = "Ignite flame", + nodenames ={"mcl_fire:fire","mcl_fire:eternal_fire"}, + interval = 7, + chance = 12, + catch_up = false, + action = function(pos) + local p = get_ignitable(pos) + if p then + add_fire_particle(p,pos) + spawn_fire(p) + shuffle_adjacents() + end + end + }) + + -- Set fire to air nodes minetest.register_abm({ label = "Ignite fire by lava", nodenames = {"group:lava"}, - neighbors = {"air"}, + nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"}, + neighbors = {"air","group:flammable"}, interval = 7, chance = 3, catch_up = false, action = function(pos) - local i, dir, target, node, i2, f - i = math.random(1,9) - dir = lava_fire[i] - target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} - node = get_node(target) - if not node or node.name ~= "air" then - i = ((i + math.random(0,7)) % 9) + 1 - dir = lava_fire[i] - target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} - node = get_node(target) - if not node or node.name ~= "air" then - return - end - end - i2 = math.random(1,15) - if i2 < 10 then - local dir2, target2, node2 - dir2 = lava_fire[i2] - target2 = {x=target.x+dir2.x, y=target.y+dir2.y, z=target.z+dir2.z} - node2 = get_node(target2) - if node2 and node2.name == "air" then - f = has_flammable(target2) - if f then - minetest.after(1, spawn_fire, {x=target2.x, y=target2.y, z=target2.z}) - minetest.add_particle({ - pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), - velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.7), z=f.z-pos.z}, - expirationtime=1, size=1.5, collisiondetection=false, - glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" - }) - return - end - end - end - f = has_flammable(target) - if f then - minetest.after(1, spawn_fire, {x=target.x, y=target.y, z=target.z}) - minetest.add_particle({ - pos = vector.new({x=pos.x, y=pos.y+0.5, z=pos.z}), - velocity={x=f.x-pos.x, y=math.max(f.y-pos.y,0.25), z=f.z-pos.z}, - expirationtime=1, size=1, collisiondetection=false, - glow=minetest.LIGHT_MAX, texture="mcl_particles_flame.png" - }) + local p=get_ignitable_by_lava(pos) + if p then + add_fire_particle(p,pos) + spawn_fire(p) end end, }) + -- Remove flammable nodes around basic flame + minetest.register_abm({ + label = "Remove flammable nodes", + nodenames = {"mcl_fire:fire","mcl_fire:eternal_fire"}, + neighbors = {"group:flammable"}, + interval = 5, + chance = 18, + catch_up = false, + action = function(pos) + local p = has_flammable(pos) + if not p then + return + end + + local nn = minetest.get_node(p).name + local def = minetest.registered_nodes[nn] + local fgroup = minetest.get_item_group(nn, "flammable") + + if def and def._on_burn then + def._on_burn(p) + elseif fgroup ~= -1 then + add_fire_particle(p,pos) + spawn_fire(p) + fire_timer(p) + minetest.check_for_falling(p) + end + end + }) + end -- Set pointed_thing on (normal) fire. diff --git a/mods/ITEMS/mcl_shields/init.lua b/mods/ITEMS/mcl_shields/init.lua new file mode 100644 index 000000000..3ac58fc3c --- /dev/null +++ b/mods/ITEMS/mcl_shields/init.lua @@ -0,0 +1,469 @@ +local minetest, math, vector = minetest, math, vector +local modname = minetest.get_current_modname() +local S = minetest.get_translator(modname) + +mcl_shields = { + types = { + mob = true, + player = true, + arrow = true, + generic = true, + explosion = true, -- ghasts don't work + dragon_breath = true, + }, + enchantments = {"mending", "unbreaking"}, + players = {}, +} + +local interact_priv = minetest.registered_privileges.interact +interact_priv.give_to_singleplayer = false +interact_priv.give_to_admin = false + +local overlay = mcl_enchanting.overlay +local hud = "mcl_shield_hud.png" + +minetest.register_tool("mcl_shields:shield", { + description = S("Shield"), + _doc_items_longdesc = S("A shield is a tool used for protecting the player against attacks."), + inventory_image = "mcl_shield.png", + stack_max = 1, + groups = { + 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), +}) + +local function wielded_item(obj, i) + local itemstack = obj:get_wielded_item() + if i == 1 then + itemstack = obj:get_inventory():get_stack("offhand", 1) + end + return itemstack:get_name() +end + +function mcl_shields.wielding_shield(obj, i) + return wielded_item(obj, i):find("mcl_shields:shield") +end + +local function shield_is_enchanted(obj, i) + return mcl_enchanting.is_enchanted(wielded_item(obj, i)) +end + +minetest.register_entity("mcl_shields:shield_entity", { + initial_properties = { + visual = "mesh", + mesh = "mcl_shield.obj", + physical = false, + pointable = false, + collide_with_objects = false, + textures = {"mcl_shield_base_nopattern.png"}, + visual_size = vector.new(1, 1, 1), + }, + _blocking = false, + _shield_number = 2, + on_step = function(self, dtime, moveresult) + local player = self.object:get_attach() + if player then + local shield_texture = "mcl_shield_base_nopattern.png" + local i = self._shield_number + local item = wielded_item(player, i) + + if item ~= "mcl_shields:shield" and item ~= "mcl_shields:shield_enchanted" then + local itemstack = player:get_wielded_item() + if i == 1 then + itemstack = player:get_inventory():get_stack("offhand", 1) + end + local meta_texture = itemstack:get_meta():get_string("mcl_shields:shield_custom_pattern_texture") + if meta_texture ~= "" then + shield_texture = meta_texture + else + local color = minetest.registered_items[item]._shield_color + if color then + shield_texture = "mcl_shield_base_nopattern.png^(mcl_shield_pattern_base.png^[colorize:" .. color .. ")" + end + + end + end + + if shield_is_enchanted(player, i) then + shield_texture = shield_texture .. overlay + end + + self.object:set_properties({textures = {shield_texture}}) + else + self.object:remove() + end + end, +}) + +for _, e in pairs(mcl_shields.enchantments) do + mcl_enchanting.enchantments[e].secondary.shield = true +end + +function mcl_shields.is_blocking(obj) + local blocking = mcl_shields.players[obj].blocking + if blocking > 0 then + local shieldstack = obj:get_wielded_item() + if blocking == 1 then + shieldstack = obj:get_inventory():get_stack("offhand", 1) + end + return blocking, shieldstack + end +end + +mcl_damage.register_modifier(function(obj, damage, reason) + local type = reason.type + local damager = reason.direct + local blocking, shieldstack = mcl_shields.is_blocking(obj) + if obj:is_player() and blocking and mcl_shields.types[type] and damager then + local entity = damager:get_luaentity() + if entity and (type == "arrow" or type == "generic") then + damager = entity._shooter + end + if vector.dot(obj:get_look_dir(), vector.subtract(damager:get_pos(), obj:get_pos())) >= 0 then + local durability = 336 + local unbreaking = mcl_enchanting.get_enchantment(shieldstack, mcl_shields.enchantments[2]) + if unbreaking > 0 then + durability = durability * (unbreaking + 1) + end + if not minetest.is_creative_enabled(obj:get_player_name()) and damage >= 3 then + shieldstack:add_wear(65535 / durability) + if blocking == 2 then + obj:set_wielded_item(shieldstack) + else + obj:get_inventory():set_stack("offhand", 1, shieldstack) + mcl_inventory.update_inventory_formspec(obj) + end + end + minetest.sound_play({name = "mcl_block"}) + return 0 + end + end +end) + +local function modify_shield(player, vpos, vrot, i) + local arm = "Right" + if i == 1 then + arm = "Left" + end + local shield = mcl_shields.players[player].shields[i] + if shield then + shield:set_attach(player, "Arm_" .. arm, vpos, vrot, false) + end +end + +local function set_shield(player, block, i) + if block then + if i == 1 then + modify_shield(player, vector.new(-9, 4, 0.5), vector.new(80, 100, 0), i) -- TODO + else + modify_shield(player, vector.new(-8, 4, -2.5), vector.new(80, 80, 0), i) + end + else + if i == 1 then + modify_shield(player, vector.new(-3, -5, 0), vector.new(0, 180, 0), i) + else + modify_shield(player, vector.new(3, -5, 0), vector.new(0, 0, 0), i) + end + end + local shield = mcl_shields.players[player].shields[i] + if not shield then return end + local luaentity = shield:get_luaentity() + if not luaentity then return end + luaentity._blocking = block +end + +local function set_interact(player, interact) + local player_name = player:get_player_name() + local privs = minetest.get_player_privs(player_name) + if privs.interact ~= interact then + privs.interact = interact + minetest.set_player_privs(player_name, privs) + end +end + +local shield_hud = {} + +local function remove_shield_hud(player) + if shield_hud[player] then + player:hud_remove(shield_hud[player]) + shield_hud[player] = nil + set_shield(player, false, 1) + set_shield(player, false, 2) + end + + local hf=player:hud_get_flags() + if not hf.wielditem then + player:hud_set_flags({wielditem = true}) + end + + playerphysics.remove_physics_factor(player, "speed", "shield_speed") + set_interact(player, true) +end + +local function add_shield_entity(player, i) + local shield = minetest.add_entity(player:get_pos(), "mcl_shields:shield_entity") + shield:get_luaentity()._shield_number = i + mcl_shields.players[player].shields[i] = shield + set_shield(player, false, i) +end + +local function remove_shield_entity(player, i) + local shields = mcl_shields.players[player].shields + if shields[i] then + shields[i]:remove() + shields[i] = nil + end +end + +local function handle_blocking(player) + local player_shield = mcl_shields.players[player] + local rmb = player:get_player_control().RMB + if rmb then + local shield_in_offhand = mcl_shields.wielding_shield(player, 1) + local shield_in_hand = mcl_shields.wielding_shield(player) + local not_blocking = player_shield.blocking == 0 + + local pos = player:get_pos() + if shield_in_hand then + if not_blocking then + minetest.after(0.25, function() + if (not_blocking or not shield_in_offhand) and shield_in_hand and rmb then + player_shield.blocking = 2 + set_shield(player, true, 2) + end + end) + elseif not shield_in_offhand then + player_shield.blocking = 2 + end + elseif shield_in_offhand then + local offhand_can_block = (wielded_item(player) == "" or not mcl_util.get_pointed_thing(player)) + if offhand_can_block then + if not_blocking then + minetest.after(0.25, function() + if (not_blocking or not shield_in_hand) and shield_in_offhand and rmb and offhand_can_block then + player_shield.blocking = 1 + set_shield(player, true, 1) + end + end) + elseif not shield_in_hand then + player_shield.blocking = 1 + end + end + else + player_shield.blocking = 0 + end + else + player_shield.blocking = 0 + end +end + +local function update_shield_entity(player, blocking, i) + local shield = mcl_shields.players[player].shields[i] + if mcl_shields.wielding_shield(player, i) then + if not shield then + add_shield_entity(player, i) + else + if blocking == i then + if shield:get_luaentity() and not shield:get_luaentity()._blocking then + set_shield(player, true, i) + end + else + set_shield(player, false, i) + end + end + elseif shield then + remove_shield_entity(player, i) + end +end + +minetest.register_globalstep(function(dtime) + for _, player in pairs(minetest.get_connected_players()) do + + handle_blocking(player) + + local blocking, shieldstack = mcl_shields.is_blocking(player) + + if blocking then + local shieldhud = shield_hud[player] + if not shieldhud then + local texture = hud + if mcl_enchanting.is_enchanted(shieldstack:get_name()) then + texture = texture .. overlay + end + local offset = 100 + if blocking == 1 then + texture = texture .. "^[transform4" + offset = -100 + else + player:hud_set_flags({wielditem = false}) + end + shield_hud[player] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.5}, + scale = {x = -101, y = -101}, + offset = {x = offset, y = 0}, + text = texture, + z_index = -200, + }) + playerphysics.add_physics_factor(player, "speed", "shield_speed", 0.5) + set_interact(player, nil) + else + local wielditem = player:hud_get_flags().wielditem + if blocking == 1 then + if not wielditem then + player:hud_change(shieldhud, "text", hud .. "^[transform4") + player:hud_change(shieldhud, "offset", {x = -100, y = 0}) + player:hud_set_flags({wielditem = true}) + end + else + if wielditem then + player:hud_change(shieldhud, "text", hud) + player:hud_change(shieldhud, "offset", {x = 100, y = 0}) + player:hud_set_flags({wielditem = false}) + end + end + + local image = player:hud_get(shieldhud).text + local enchanted = hud .. overlay + local enchanted1 = image == enchanted + local enchanted2 = image == enchanted .. "^[transform4" + if mcl_enchanting.is_enchanted(shieldstack:get_name()) then + if not enchanted1 and not enchanted2 then + if blocking == 1 then + player:hud_change(shieldhud, "text", hud .. overlay .. "^[transform4") + else + player:hud_change(shieldhud, "text", hud .. overlay) + end + end + elseif enchanted1 or enchanted2 then + if blocking == 1 then + player:hud_change(shieldhud, "text", hud .. "^[transform4") + else + player:hud_change(shieldhud, "text", hud) + end + end + end + else + remove_shield_hud(player) + end + + for i = 1, 2 do + update_shield_entity(player, blocking, i) + end + end +end) + +minetest.register_on_dieplayer(function(player) + remove_shield_hud(player) + if not minetest.settings:get_bool("mcl_keepInventory") then + remove_shield_entity(player, 1) + remove_shield_entity(player, 2) + end +end) + +minetest.register_on_leaveplayer(function(player) + shield_hud[player] = nil + mcl_shields.players[player] = nil +end) + +minetest.register_craft({ + output = "mcl_shields:shield", + recipe = { + {"group:wood", "mcl_core:iron_ingot", "group:wood"}, + {"group:wood", "group:wood", "group:wood"}, + {"", "group:wood", ""}, + } +}) + +for _, colortab in pairs(mcl_banners.colors) do + minetest.register_tool("mcl_shields:shield_" .. colortab[1], { + description = S(colortab[6] .. " Shield"), + _doc_items_longdesc = S("A shield is a tool used for protecting the player against attacks."), + inventory_image = "mcl_shield.png^(mcl_shield_item_overlay.png^[colorize:" .. colortab[4] ..")", + stack_max = 1, + groups = { + shield = 1, + weapon = 1, + enchantability = 1, + no_wieldview = 1, + not_in_creative_inventory = 1, + offhand_item = 1, + }, + sound = {breaks = "default_tool_breaks"}, + _repair_material = "group:wood", + wield_scale = vector.new(2, 2, 2), + _shield_color = colortab[4], + }) + + local banner = "mcl_banners:banner_item_" .. colortab[1] + minetest.register_craft({ + type = "shapeless", + output = "mcl_shields:shield_" .. colortab[1], + recipe = {"mcl_shields:shield", banner}, + }) +end + +local function to_shield_texture(banner_texture) + return banner_texture + :gsub("mcl_banners_base_inverted.png", "mcl_shield_base_nopattern.png^mcl_shield_pattern_base.png") + :gsub("mcl_banners_banner_base.png", "mcl_shield_base_nopattern.png^mcl_shield_pattern_base.png") + :gsub("mcl_banners_base", "mcl_shield_pattern_base") + :gsub("mcl_banners", "mcl_shield_pattern") +end + +local function craft_banner_on_shield(itemstack, player, old_craft_grid, craft_inv) + if string.find(itemstack:get_name(), "mcl_shields:shield_") then + local shield_stack + for i = 1, player:get_inventory():get_size("craft") do + local stack = old_craft_grid[i] + local name = stack:get_name() + if name == "mcl_shields:shield" then + shield_stack = stack + break + end + end + for i = 1, player:get_inventory():get_size("craft") do + local banner_stack = old_craft_grid[i] + local banner_name = banner_stack:get_name() + if string.find(banner_name, "mcl_banners:banner") and shield_stack then + local banner_meta = banner_stack:get_meta() + local layers_meta = banner_meta:get_string("layers") + local new_shield_meta = itemstack:get_meta() + if layers_meta ~= "" then + local color = mcl_banners.color_reverse(banner_name) + local layers = minetest.deserialize(layers_meta) + local texture = mcl_banners.make_banner_texture(color, layers) + new_shield_meta:set_string("description", mcl_banners.make_advanced_banner_description(itemstack:get_description(), layers)) + new_shield_meta:set_string("mcl_shields:shield_custom_pattern_texture", to_shield_texture(texture)) + end + itemstack:set_wear(shield_stack:get_wear()) + break + end + end + end + return itemstack +end + +minetest.register_craft_predict(function(itemstack, player, old_craft_grid, craft_inv) + return craft_banner_on_shield(itemstack, player, old_craft_grid, craft_inv) +end) + +minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) + return craft_banner_on_shield(itemstack, player, old_craft_grid, craft_inv) +end) + +minetest.register_on_joinplayer(function(player) + mcl_shields.players[player] = { + shields = {}, + blocking = 0, + } + mcl_shields.players[player].blocking = 0 + remove_shield_hud(player) +end) diff --git a/mods/ITEMS/mcl_shields/locale/mcl_shields.de.tr b/mods/ITEMS/mcl_shields/locale/mcl_shields.de.tr new file mode 100644 index 000000000..2a4deccc0 --- /dev/null +++ b/mods/ITEMS/mcl_shields/locale/mcl_shields.de.tr @@ -0,0 +1,19 @@ +# textdomain: mcl_shields +Shield=Schild +A shield is a tool used for protecting the player against attacks.=Der Schild ist eine Schutzwaffe, die den Spieler vor Angriffen schützt. +White Shield=Weißer Schild +Grey Shield=Grauer Schild +Light Grey Shield=Hellgrauer Schild +Black Shield=Schwarzer Schild +Red Shield=Roter Schild +Yellow Shield=Gelber Schild +Green Shield=Grüner Schild +Cyan Shield=Türkiser Schild +Blue Shield=Blauer Schild +Magenta Shield=Magenta Schild +Orange Shield=Oranger Schild +Purple Shield=Violetter Schild +Brown Shield=Brauner Schild +Pink Shield=Rosa Schild +Lime Shield=Hellgrüner Schild +Light Blue Shield=Hellblauer Schild diff --git a/mods/ITEMS/mcl_shields/locale/template.txt b/mods/ITEMS/mcl_shields/locale/template.txt new file mode 100644 index 000000000..bcf7b1b54 --- /dev/null +++ b/mods/ITEMS/mcl_shields/locale/template.txt @@ -0,0 +1,19 @@ +# textdomain: mcl_shields +Shield= +A shield is a tool used for protecting the player against attacks.= +White Shield= +Grey Shield= +Light Grey Shield= +Black Shield= +Red Shield= +Yellow Shield= +Green Shield= +Cyan Shield= +Blue Shield= +Magenta Shield= +Orange Shield= +Purple Shield= +Brown Shield= +Pink Shield= +Lime Shield= +Light Blue Shield= diff --git a/mods/ITEMS/mcl_shields/mod.conf b/mods/ITEMS/mcl_shields/mod.conf new file mode 100644 index 000000000..8aded6a62 --- /dev/null +++ b/mods/ITEMS/mcl_shields/mod.conf @@ -0,0 +1,3 @@ +name = mcl_shields +author = NO11 +depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics diff --git a/mods/ITEMS/mcl_shields/models/mcl_shield.obj b/mods/ITEMS/mcl_shields/models/mcl_shield.obj new file mode 100644 index 000000000..b1cf77c28 --- /dev/null +++ b/mods/ITEMS/mcl_shields/models/mcl_shield.obj @@ -0,0 +1,88 @@ +# Blender v3.0.0 OBJ File: '' +# www.blender.org +mtllib mcl_shield.mtl +o Cube.002_Cube.003 +v 4.663009 11.096291 6.387994 +v 4.663009 4.596560 5.241916 +v 5.213008 4.596560 5.241916 +v 5.213008 11.096291 6.387994 +v 5.213007 13.197435 -5.528180 +v 5.213007 6.697705 -6.674258 +v 4.663008 6.697705 -6.674258 +v 4.663008 13.197435 -5.528180 +v 4.663008 8.641873 -1.863572 +v 4.663008 8.068833 1.386293 +v 1.363008 8.068833 1.386294 +v 1.363008 8.641873 -1.863572 +v 1.363008 9.152122 1.577307 +v 1.363008 9.725162 -1.672559 +v 4.663008 9.152122 1.577306 +v 4.663008 9.725162 -1.672559 +vt 0.015625 0.984375 +vt 0.203125 0.984375 +vt 0.203125 1.000000 +vt 0.015625 1.000000 +vt 0.203125 0.640625 +vt 0.203125 0.984375 +vt 0.015625 0.984375 +vt 0.015625 0.640625 +vt 0.015625 0.984375 +vt 0.015625 0.640625 +vt -0.000000 0.640625 +vt -0.000000 0.984375 +vt 0.203125 0.984375 +vt 0.390625 0.984375 +vt 0.390625 1.000000 +vt 0.203125 1.000000 +vt 0.203125 0.984375 +vt 0.203125 0.640625 +vt 0.218750 0.640625 +vt 0.218750 0.984375 +vt 0.406250 0.640625 +vt 0.406250 0.984375 +vt 0.218750 0.984375 +vt 0.218750 0.640625 +vt 0.531250 0.812500 +vt 0.625000 0.812500 +vt 0.625000 0.906250 +vt 0.531250 0.906250 +vt 0.500000 0.906250 +vt 0.500000 0.812500 +vt 0.531250 0.812500 +vt 0.531250 0.906250 +vt 0.406250 0.812500 +vt 0.500000 0.812500 +vt 0.500000 0.906250 +vt 0.406250 0.906250 +vt 0.625000 0.812500 +vt 0.656250 0.812500 +vt 0.656250 0.906250 +vt 0.625000 0.906250 +vt 0.562500 1.000000 +vt 0.531250 1.000000 +vt 0.531250 0.906250 +vt 0.562500 0.906250 +vt 0.531250 1.000000 +vt 0.500000 1.000000 +vt 0.500000 0.906250 +vt 0.531250 0.906250 +vn 0.0000 -0.1736 0.9848 +vn 1.0000 0.0000 -0.0000 +vn 0.0000 -0.9848 -0.1736 +vn 0.0000 0.1736 -0.9848 +vn 0.0000 0.9848 0.1736 +vn -1.0000 -0.0000 0.0000 +usemtl Material.002 +s 1 +f 1/1/1 2/2/1 3/3/1 4/4/1 +f 5/5/2 4/6/2 3/7/2 6/8/2 +f 6/9/3 3/10/3 2/11/3 7/12/3 +f 7/13/4 8/14/4 5/15/4 6/16/4 +f 8/17/5 1/18/5 4/19/5 5/20/5 +f 7/21/6 2/22/6 1/23/6 8/24/6 +f 9/25/3 10/26/3 11/27/3 12/28/3 +f 12/29/6 11/30/6 13/31/6 14/32/6 +f 14/33/5 13/34/5 15/35/5 16/36/5 +f 16/37/2 15/38/2 10/39/2 9/40/2 +f 12/41/4 14/42/4 16/43/4 9/44/4 +f 13/45/1 11/46/1 10/47/1 15/48/1 diff --git a/mods/ITEMS/mcl_shields/sounds/mcl_block.ogg b/mods/ITEMS/mcl_shields/sounds/mcl_block.ogg new file mode 100644 index 000000000..3af7f04b4 Binary files /dev/null and b/mods/ITEMS/mcl_shields/sounds/mcl_block.ogg differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield.png b/mods/ITEMS/mcl_shields/textures/mcl_shield.png new file mode 100644 index 000000000..7391636e9 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_base_nopattern.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_base_nopattern.png new file mode 100644 index 000000000..8146632bb Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_base_nopattern.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png new file mode 100644 index 000000000..4286d3e83 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_hud.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_item_overlay.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_item_overlay.png new file mode 100644 index 000000000..3e7953609 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_item_overlay.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_base.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_base.png new file mode 100644 index 000000000..268445b36 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_base.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_border.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_border.png new file mode 100644 index 000000000..e128218e6 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_border.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_bricks.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_bricks.png new file mode 100644 index 000000000..f1ddd716b Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_bricks.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_circle.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_circle.png new file mode 100644 index 000000000..8ff66b8c8 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_circle.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_creeper.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_creeper.png new file mode 100644 index 000000000..5b30dc76b Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_creeper.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_cross.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_cross.png new file mode 100644 index 000000000..40a6624ae Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_cross.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_curly_border.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_curly_border.png new file mode 100644 index 000000000..9f8c21773 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_curly_border.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_left.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_left.png new file mode 100644 index 000000000..a04a6fdc0 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_left.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_right.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_right.png new file mode 100644 index 000000000..309f711bf Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_right.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_up_left.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_up_left.png new file mode 100644 index 000000000..c5f4399a0 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_up_left.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_up_right.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_up_right.png new file mode 100644 index 000000000..59dd957dd Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_diagonal_up_right.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_flower.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_flower.png new file mode 100644 index 000000000..fe7ca826f Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_flower.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_gradient.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_gradient.png new file mode 100644 index 000000000..29a98c704 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_gradient.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_gradient_up.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_gradient_up.png new file mode 100644 index 000000000..09effb26a Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_gradient_up.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_horizontal.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_horizontal.png new file mode 100644 index 000000000..5187803b3 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_horizontal.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_horizontal_bottom.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_horizontal_bottom.png new file mode 100644 index 000000000..515e6ddfe Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_horizontal_bottom.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_vertical.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_vertical.png new file mode 100644 index 000000000..9a56804da Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_vertical.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_vertical_right.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_vertical_right.png new file mode 100644 index 000000000..4a5af61fb Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_half_vertical_right.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_rhombus.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_rhombus.png new file mode 100644 index 000000000..13b502289 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_rhombus.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_skull.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_skull.png new file mode 100644 index 000000000..4e0c7c1f5 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_skull.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_small_stripes.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_small_stripes.png new file mode 100644 index 000000000..f125ba2fb Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_small_stripes.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_bottom_left.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_bottom_left.png new file mode 100644 index 000000000..a5c4e00c0 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_bottom_left.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_bottom_right.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_bottom_right.png new file mode 100644 index 000000000..ca2c53692 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_bottom_right.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_top_left.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_top_left.png new file mode 100644 index 000000000..2123cba15 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_top_left.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_top_right.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_top_right.png new file mode 100644 index 000000000..3f7a759a8 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_square_top_right.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_straight_cross.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_straight_cross.png new file mode 100644 index 000000000..dc861f048 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_straight_cross.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_bottom.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_bottom.png new file mode 100644 index 000000000..859ad11d1 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_bottom.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_center.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_center.png new file mode 100644 index 000000000..8d1e2404c Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_center.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_downleft.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_downleft.png new file mode 100644 index 000000000..c0a93cd4f Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_downleft.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_downright.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_downright.png new file mode 100644 index 000000000..09580857c Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_downright.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_left.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_left.png new file mode 100644 index 000000000..6e5bcb02e Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_left.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_middle.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_middle.png new file mode 100644 index 000000000..af5ebc12a Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_middle.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_right.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_right.png new file mode 100644 index 000000000..dcb911b68 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_right.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_top.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_top.png new file mode 100644 index 000000000..a1e10be46 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_stripe_top.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_thing.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_thing.png new file mode 100644 index 000000000..43b2a1d49 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_thing.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangle_bottom.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangle_bottom.png new file mode 100644 index 000000000..87d1aa95b Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangle_bottom.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangle_top.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangle_top.png new file mode 100644 index 000000000..94d652878 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangle_top.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangles_bottom.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangles_bottom.png new file mode 100644 index 000000000..3e4851abb Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangles_bottom.png differ diff --git a/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangles_top.png b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangles_top.png new file mode 100644 index 000000000..0ae85d6d1 Binary files /dev/null and b/mods/ITEMS/mcl_shields/textures/mcl_shield_pattern_triangles_top.png differ diff --git a/mods/ITEMS/mcl_totems/init.lua b/mods/ITEMS/mcl_totems/init.lua index b11e68df7..7a45ea58f 100644 --- a/mods/ITEMS/mcl_totems/init.lua +++ b/mods/ITEMS/mcl_totems/init.lua @@ -12,6 +12,14 @@ mcl_damage.register_modifier(function(obj, damage, reason) local hp = obj:get_hp() if hp - damage <= 0 then local wield = obj:get_wielded_item() + local in_offhand = false + if not (wield:get_name() == "mobs_mc:totem") then + local inv = obj:get_inventory() + if inv then + wield = obj:get_inventory():get_stack("offhand", 1) + in_offhand = true + end + end if wield:get_name() == "mobs_mc:totem" then local ppos = obj:get_pos() local pnname = minetest.get_node(ppos).name @@ -28,7 +36,12 @@ mcl_damage.register_modifier(function(obj, damage, reason) if not minetest.is_creative_enabled(obj:get_player_name()) then wield:take_item() - obj:set_wielded_item(wield) + if in_offhand then + obj:get_inventory():set_stack("offhand", 1, wield) + mcl_inventory.update_inventory_formspec(obj) + else + obj:set_wielded_item(wield) + end end -- Effects diff --git a/mods/MISC/mcl_privs/init.lua b/mods/MISC/mcl_privs/init.lua index f06ff3582..b0d7a5066 100644 --- a/mods/MISC/mcl_privs/init.lua +++ b/mods/MISC/mcl_privs/init.lua @@ -22,8 +22,10 @@ for _, action in pairs({"grant", "revoke"}) do minetest["register_on_priv_" .. action](function(name, _, priv) if priv == "fly" then local player = minetest.get_player_by_name(name) - local meta = player:get_meta() - meta:set_int("fly_changed", 1) + if player then + local meta = player:get_meta() + meta:set_int("fly_changed", 1) + end end end) end \ No newline at end of file diff --git a/mods/PLAYER/mcl_player/init.lua b/mods/PLAYER/mcl_player/init.lua index 2a4c25c34..2c6592ac8 100644 --- a/mods/PLAYER/mcl_player/init.lua +++ b/mods/PLAYER/mcl_player/init.lua @@ -9,7 +9,8 @@ local animation_blend = 0 local function get_mouse_button(player) local controls = player:get_player_control() local get_wielded_item_name = player:get_wielded_item():get_name() - if controls.RMB and not string.find(get_wielded_item_name, "mcl_bows:bow") and not string.find(get_wielded_item_name, "mcl_bows:crossbow") or controls.LMB then + if controls.RMB and not string.find(get_wielded_item_name, "mcl_bows:bow") and not string.find(get_wielded_item_name, "mcl_bows:crossbow") and + not mcl_shields.wielding_shield(player, 1) and not mcl_shields.wielding_shield(player, 2) or controls.LMB then return true else return false @@ -188,6 +189,9 @@ minetest.register_globalstep(function(dtime) animation_speed_mod = animation_speed_mod / 2 end + if mcl_shields.is_blocking(player) then + animation_speed_mod = animation_speed_mod / 2 + end -- ask if player is swiming @@ -204,6 +208,8 @@ minetest.register_globalstep(function(dtime) or walking and velocity.x < -0.35 or walking and velocity.z > 0.35 or walking and velocity.z < -0.35 then + local wielded_itemname = player:get_wielded_item():get_name() + local no_arm_moving = string.find(wielded_itemname, "mcl_bows:bow") or mcl_shields.wielding_shield(player, 1) or mcl_shields.wielding_shield(player, 2) if player_sneak[name] ~= controls.sneak then player_anim[name] = nil player_sneak[name] = controls.sneak @@ -212,9 +218,9 @@ minetest.register_globalstep(function(dtime) player_set_animation(player, "swim_walk_mine", animation_speed_mod) elseif not controls.sneak and head_in_water and is_sprinting == true then player_set_animation(player, "swim_walk", animation_speed_mod) - elseif string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB and controls.sneak or string.find(player:get_wielded_item():get_name(), "mcl_bows:crossbow_") and controls.sneak then + elseif no_arm_moving and controls.RMB and controls.sneak or string.find(wielded_itemname, "mcl_bows:crossbow_") and controls.sneak then player_set_animation(player, "bow_sneak", animation_speed_mod) - elseif string.find(player:get_wielded_item():get_name(), "mcl_bows:bow") and controls.RMB or string.find(player:get_wielded_item():get_name(), "mcl_bows:crossbow_") then + elseif no_arm_moving and controls.RMB or string.find(wielded_itemname, "mcl_bows:crossbow_") then player_set_animation(player, "bow_walk", animation_speed_mod) elseif is_sprinting == true and get_mouse_button(player) == true and not controls.sneak and not head_in_water then player_set_animation(player, "run_walk_mine", animation_speed_mod) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index 825a468b1..720c11525 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -336,8 +336,12 @@ minetest.register_globalstep(function(dtime) player_velocity_old = player:get_velocity() or player:get_player_velocity() - -- controls right and left arms pitch when shooting a bow - if string.find(wielded:get_name(), "mcl_bows:bow") and control.RMB then + -- controls right and left arms pitch when shooting a bow or blocking + if mcl_shields.is_blocking(player) == 2 then + set_bone_position_conditional(player, "Arm_Right_Pitch_Control", vector.new(-3, 5.785, 0), vector.new(20, -20, 0)) + elseif mcl_shields.is_blocking(player) == 1 then + set_bone_position_conditional(player, "Arm_Left_Pitch_Control", vector.new(3, 5.785, 0), vector.new(20, 20, 0)) + elseif string.find(wielded:get_name(), "mcl_bows:bow") and control.RMB then set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch+90,-30,pitch * -1 * .35)) set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35)) -- controls right and left arms pitch when holing a loaded crossbow diff --git a/mods/PLAYER/mcl_playerplus/mod.conf b/mods/PLAYER/mcl_playerplus/mod.conf index b77c9e2e5..374178625 100644 --- a/mods/PLAYER/mcl_playerplus/mod.conf +++ b/mods/PLAYER/mcl_playerplus/mod.conf @@ -1,5 +1,5 @@ name = mcl_playerplus author = TenPlus1 description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more. -depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage, mcl_sprint +depends = mcl_init, mcl_core, mcl_particles, mcl_hunger, playerphysics, mcl_playerinfo, mcl_weather, mcl_spawn, mcl_enchanting, mcl_damage, mcl_sprint, mcl_shields diff --git a/mods/PLAYER/mcl_wieldview/init.lua b/mods/PLAYER/mcl_wieldview/init.lua index 7200f6186..92175a17e 100644 --- a/mods/PLAYER/mcl_wieldview/init.lua +++ b/mods/PLAYER/mcl_wieldview/init.lua @@ -6,7 +6,7 @@ mcl_wieldview = { } function mcl_wieldview.get_item_texture(itemname) - if itemname == "" then + if itemname == "" or minetest.get_item_group(itemname, "no_wieldview") ~= 0 then return end @@ -41,14 +41,19 @@ function mcl_wieldview.update_wielded_item(player) local def = mcl_wieldview.players[player] - if def.item == itemname then + if def and (def.item == itemname) then return end - def.item = itemname - def.texture = mcl_wieldview.get_item_texture(itemname) or "blank.png" + local texture = mcl_wieldview.get_item_texture(itemname) or "blank.png" - mcl_player.player_set_wielditem(player, def.texture) + local new_def = { + item = itemname, + texture = texture, + } + mcl_wieldview.players[player] = new_def + + mcl_player.player_set_wielditem(player, texture) end minetest.register_on_joinplayer(function(player) @@ -113,6 +118,10 @@ minetest.register_entity("mcl_wieldview:wieldnode", { 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