Merge pull request 'master' (#1) from MineClone5/MineClone5:master into master

Reviewed-on: #1
This commit is contained in:
NO11 2022-01-31 16:38:37 +00:00
commit 2be3a83aa8
73 changed files with 1150 additions and 322 deletions

View File

@ -485,3 +485,16 @@ function mcl_util.replace_mob(obj, mob)
obj:set_yaw(rot) obj:set_yaw(rot)
return obj return obj
end 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

View File

@ -525,7 +525,7 @@ if c("totem") then
inventory_image = "mcl_totems_totem.png", inventory_image = "mcl_totems_totem.png",
wield_image = "mcl_totems_totem.png", wield_image = "mcl_totems_totem.png",
stack_max = 1, stack_max = 1,
groups = {combat_item=1}, groups = {combat_item = 1, offhand_item = 1},
}) })
end end

View File

@ -1,5 +1,5 @@
local PARTICLES_COUNT_RAIN = 30 local PARTICLES_COUNT_RAIN = 100
local PARTICLES_COUNT_THUNDER = 45 local PARTICLES_COUNT_THUNDER = 300
local get_connected_players = minetest.get_connected_players local get_connected_players = minetest.get_connected_players
@ -19,6 +19,45 @@ mcl_weather.rain = {
init_done = false, 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) function mcl_weather.rain.sound_handler(player)
return minetest.sound_play("weather_rain", { return minetest.sound_play("weather_rain", {
@ -44,44 +83,20 @@ function mcl_weather.rain.set_sky_box()
end end
end end
-- creating manually parctiles instead of particles spawner because of easier to control -- no no no NO NO f*.. no. no manual particle creatin' PLS!! this sends EVERY particle over the net.
-- spawn position.
function mcl_weather.rain.add_rain_particles(player) function mcl_weather.rain.add_rain_particles(player)
mcl_weather.rain.last_rp_count = 0 mcl_weather.rain.last_rp_count = mcl_weather.rain.particles_count
for i=mcl_weather.rain.particles_count, 1,-1 do for k,v in pairs(textures) do
local random_pos_x, random_pos_y, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player) psdef.texture=v
if mcl_weather.is_outdoor({x=random_pos_x, y=random_pos_y, z=random_pos_z}) then mcl_weather.add_spawner_player(player,"rain"..k,psdef)
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 end
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 end
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"
end
return texture_name;
end
-- register player for rain weather. -- register player for rain weather.
-- basically needs for origin sky reference and rain sound controls. -- basically needs for origin sky reference and rain sound controls.
function mcl_weather.rain.add_player(player) function mcl_weather.rain.add_player(player)
@ -89,6 +104,7 @@ function mcl_weather.rain.add_player(player)
local player_meta = {} local player_meta = {}
player_meta.origin_sky = {player:get_sky()} player_meta.origin_sky = {player:get_sky()}
mcl_weather.players[player:get_player_name()] = player_meta mcl_weather.players[player:get_player_name()] = player_meta
update_sound[player:get_player_name()]=true
end end
end end
@ -99,6 +115,7 @@ function mcl_weather.rain.remove_player(player)
if player_meta and player_meta.origin_sky then if player_meta and player_meta.origin_sky then
player:set_clouds({color="#FFF0F0E5"}) player:set_clouds({color="#FFF0F0E5"})
mcl_weather.players[player:get_player_name()] = nil mcl_weather.players[player:get_player_name()] = nil
update_sound[player:get_player_name()]=true
end end
end end
@ -119,6 +136,7 @@ end)
-- have few seconds delay before each check to avoid on/off sound too often -- 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. -- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance.
function mcl_weather.rain.update_sound(player) 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()] local player_meta = mcl_weather.players[player:get_player_name()]
if player_meta then if player_meta then
if player_meta.sound_updated and player_meta.sound_updated + 5 > minetest.get_gametime() 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() player_meta.sound_updated = minetest.get_gametime()
end end
update_sound[player:get_player_name()]=false
end end
-- rain sound removed from player. -- rain sound removed from player.
@ -158,6 +177,7 @@ function mcl_weather.rain.clear()
for _, player in pairs(get_connected_players()) do for _, player in pairs(get_connected_players()) do
mcl_weather.rain.remove_sound(player) mcl_weather.rain.remove_sound(player)
mcl_weather.rain.remove_player(player) mcl_weather.rain.remove_player(player)
mcl_weather.remove_spawners_player(player)
end end
end end
@ -177,8 +197,10 @@ function mcl_weather.rain.make_weather()
end end
for _, player in pairs(get_connected_players()) do 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.rain.remove_sound(player)
mcl_weather.remove_spawners_player(player)
return false return false
end end
mcl_weather.rain.add_player(player) mcl_weather.rain.add_player(player)
@ -190,8 +212,12 @@ end
-- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops -- Switch the number of raindrops: "thunder" for many raindrops, otherwise for normal raindrops
function mcl_weather.rain.set_particles_mode(mode) function mcl_weather.rain.set_particles_mode(mode)
if mode == "thunder" then if mode == "thunder" then
psdef.amount=PARTICLES_COUNT_THUNDER
psdef_backsplash.amount=PARTICLES_COUNT_THUNDER
mcl_weather.rain.particles_count = PARTICLES_COUNT_THUNDER mcl_weather.rain.particles_count = PARTICLES_COUNT_THUNDER
else else
psdef.amount=PARTICLES_COUNT_RAIN
psdef_backsplash.amount=PARTICLES_COUNT_RAIN
mcl_weather.rain.particles_count = PARTICLES_COUNT_RAIN mcl_weather.rain.particles_count = PARTICLES_COUNT_RAIN
end end
end end

View File

@ -5,30 +5,25 @@ mcl_weather.snow = {}
mcl_weather.snow.particles_count = 15 mcl_weather.snow.particles_count = 15
mcl_weather.snow.init_done = false mcl_weather.snow.init_done = false
-- calculates coordinates and draw particles for snow weather local psdef= {
function mcl_weather.snow.add_snow_particles(player) amount = 99,
mcl_weather.rain.last_rp_count = 0 time = 0, --stay on til we turn it off
for i=mcl_weather.snow.particles_count, 1,-1 do minpos = vector.new(-15,-5,-15),
local random_pos_x, _, random_pos_z = mcl_weather.get_random_pos_by_player_look_dir(player) maxpos =vector.new(15,10,15),
local random_pos_y = math.random() + math.random(player:get_pos().y - 1, player:get_pos().y + 7) minvel = vector.new(0,-1,0),
if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then maxvel = vector.new(0,-4,0),
mcl_weather.rain.last_rp_count = mcl_weather.rain.last_rp_count + 1 minacc = vector.new(0,-1,0),
minetest.add_particle({ maxacc = vector.new(0,-4,0),
pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z}, minexptime = 1,
velocity = {x = math.random(-100,100)*0.001, y = math.random(-300,-100)*0.004, z = math.random(-100,100)*0.001}, maxexptime = 1,
acceleration = {x = 0, y=0, z = 0}, minsize = 0.5,
expirationtime = 8.0, maxsize = 5,
size = 1,
collisiondetection = true, collisiondetection = true,
collision_removal = true, collision_removal = true,
object_collision = false, object_collision = true,
vertical = false, vertical = true,
texture = mcl_weather.snow.get_texture(), glow = 1
playername = player:get_player_name() }
})
end
end
end
function mcl_weather.snow.set_sky_box() function mcl_weather.snow.set_sky_box()
mcl_weather.skycolor.add_layer( mcl_weather.skycolor.add_layer(
@ -48,6 +43,7 @@ end
function mcl_weather.snow.clear() function mcl_weather.snow.clear()
mcl_weather.skycolor.remove_layer("weather-pack-snow-sky") mcl_weather.skycolor.remove_layer("weather-pack-snow-sky")
mcl_weather.snow.init_done = false mcl_weather.snow.init_done = false
mcl_weather.remove_all_spawners()
end end
-- Simple random texture getter -- Simple random texture getter
@ -74,10 +70,14 @@ minetest.register_globalstep(function(dtime)
end end
for _, player in pairs(get_connected_players()) do 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 return false
end 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
end) end)

View File

@ -47,6 +47,35 @@ local function save_weather()
end end
minetest.register_on_shutdown(save_weather) 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) function mcl_weather.get_rand_end_time(min_duration, max_duration)
local r local r
if min_duration and max_duration then if min_duration and max_duration then
@ -92,36 +121,6 @@ function mcl_weather.is_underwater(player)
return false return false
end 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 local t, wci = 0, mcl_weather.check_interval
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)

View File

@ -363,6 +363,10 @@ function mcl_inventory.set_creative_formspec(player, start_i, pagenum, inv_size,
armor_slot_imgs = armor_slot_imgs .. "image[5.5,2.75;1,1;mcl_inventory_empty_armor_slot_boots.png]" armor_slot_imgs = armor_slot_imgs .. "image[5.5,2.75;1,1;mcl_inventory_empty_armor_slot_boots.png]"
end 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) local stack_size = get_stack_size(player)
-- Survival inventory slots -- Survival inventory slots
@ -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(2.5,2.75,1,1)..
mcl_formspec.get_itemslot_bg(5.5,1.3,1,1).. mcl_formspec.get_itemslot_bg(5.5,1.3,1,1)..
mcl_formspec.get_itemslot_bg(5.5,2.75,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.. armor_slot_imgs..
-- player preview -- player preview
player_preview.. player_preview..
-- crafting guide button -- crafting guide button
"image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]".. "image_button[9,1;1,1;craftguide_book.png;__mcl_craftguide;]"..
"tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]".. "tooltip[__mcl_craftguide;"..F(S("Recipe book")).."]"..

View File

@ -76,6 +76,10 @@ local function set_inventory(player, armor_change_only)
end end
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]".. local form = "size[9,8.75]"..
"background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]".. "background[-0.19,-0.25;9.41,9.49;crafting_formspec_bg.png]"..
player_preview.. 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,1,1,1)..
mcl_formspec.get_itemslot_bg(0,2,1,1).. mcl_formspec.get_itemslot_bg(0,2,1,1)..
mcl_formspec.get_itemslot_bg(0,3,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.. armor_slot_imgs..
-- craft and inventory -- craft and inventory
"label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))).."]".. "label[0,4;"..F(minetest.colorize("#313131", S("Inventory"))).."]"..
@ -112,6 +118,7 @@ local function set_inventory(player, armor_change_only)
-- achievements button -- achievements button
"image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]".. "image_button[7,3;1,1;mcl_achievements_button.png;__mcl_achievements;]"..
"tooltip[__mcl_achievements;"..F(S("Achievements")).."]".. "tooltip[__mcl_achievements;"..F(S("Achievements")).."]"..
-- for shortcuts -- for shortcuts
"listring[current_player;main]".. "listring[current_player;main]"..
"listring[current_player;armor]".. "listring[current_player;armor]"..
@ -148,8 +155,11 @@ end)
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
--init inventory --init inventory
player:get_inventory():set_width("main", 9) local inv = player:get_inventory()
player:get_inventory():set_size("main", 36) inv:set_width("main", 9)
inv:set_size("main", 36)
inv:set_size("offhand", 1)
--set hotbar size --set hotbar size
player:hud_set_hotbar_itemcount(9) player:hud_set_hotbar_itemcount(9)

View File

@ -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)

View File

@ -0,0 +1,3 @@
name = mcl_offhand
author = NO11
depends = mcl_inventory

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

View File

@ -88,6 +88,10 @@ for k,v in pairs(mcl_banners.colors) do
colors_reverse["mcl_banners:banner_item_"..v[1]] = k colors_reverse["mcl_banners:banner_item_"..v[1]] = k
end end
function mcl_banners.color_reverse(itemname)
return colors_reverse[itemname]
end
-- Add pattern/emblazoning crafting recipes -- Add pattern/emblazoning crafting recipes
dofile(modpath.."/patterncraft.lua") dofile(modpath.."/patterncraft.lua")
@ -149,7 +153,7 @@ local function on_destruct_hanging_banner(pos)
return on_destruct_banner(pos, true) return on_destruct_banner(pos, true)
end end
local function make_banner_texture(base_color, layers) function mcl_banners.make_banner_texture(base_color, layers)
local colorize local colorize
if mcl_banners.colors[base_color] then if mcl_banners.colors[base_color] then
colorize = mcl_banners.colors[base_color][4] colorize = mcl_banners.colors[base_color][4]
@ -171,11 +175,11 @@ local function make_banner_texture(base_color, layers)
finished_banner = finished_banner .. "^" .. layer finished_banner = finished_banner .. "^" .. layer
end end
return { finished_banner } return finished_banner
end end
return { base } return base
else else
return { "mcl_banners_banner_base.png" } return "mcl_banners_banner_base.png"
end end
end end
@ -192,7 +196,7 @@ local function spawn_banner_entity(pos, hanging, itemstack)
local imeta = itemstack:get_meta() local imeta = itemstack:get_meta()
local layers_raw = imeta:get_string("layers") local layers_raw = imeta:get_string("layers")
local layers = minetest.deserialize(layers_raw) 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) banner:get_luaentity():_set_textures(colorid, layers)
local mname = imeta:get_string("name") local mname = imeta:get_string("name")
if mname and mname ~= "" then if mname and mname ~= "" then
@ -604,7 +608,7 @@ local entity_standing = {
visual = "mesh", visual = "mesh",
mesh = "amc_banner.b3d", mesh = "amc_banner.b3d",
visual_size = { x=2.499, y=2.499 }, visual_size = { x=2.499, y=2.499 },
textures = make_banner_texture(), textures = {mcl_banners.make_banner_texture()},
pointable = false, pointable = false,
_base_color = nil, -- base color of banner _base_color = nil, -- base color of banner
@ -624,7 +628,7 @@ local entity_standing = {
self._layers = inp._layers self._layers = inp._layers
self._name = inp._name self._name = inp._name
self.object:set_properties({ 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 end
-- Make banner slowly swing -- Make banner slowly swing
@ -635,7 +639,7 @@ local entity_standing = {
-- Set the banner textures. This function can be used by external mods. -- Set the banner textures. This function can be used by external mods.
-- Meaning of parameters: -- Meaning of parameters:
-- * self: Lua entity reference to entity. -- * 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) _set_textures = function(self, base_color, layers)
if base_color then if base_color then
self._base_color = base_color self._base_color = base_color
@ -643,7 +647,7 @@ local entity_standing = {
if layers then if layers then
self._layers = layers self._layers = layers
end 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, end,
} }
minetest.register_entity("mcl_banners:standing_banner", entity_standing) minetest.register_entity("mcl_banners:standing_banner", entity_standing)

View File

@ -248,7 +248,7 @@ function mcl_beds.register_bed(name, def)
paramtype2 = "facedir", paramtype2 = "facedir",
is_ground_content = false, is_ground_content = false,
-- FIXME: Should be bouncy=66, but this would be a higher bounciness than slime blocks! -- 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_hardness = 0.2,
_mcl_blast_resistance = 1, _mcl_blast_resistance = 1,
sounds = def.sounds or default_sounds, 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") doc.add_entry_alias("nodes", name.."_bottom", "nodes", name.."_top")
end end

View File

@ -74,6 +74,7 @@ local ARROW_ENTITY={
_shooter=nil, -- ObjectRef of player or mob who shot it _shooter=nil, -- ObjectRef of player or mob who shot it
_is_arrow = true, _is_arrow = true,
_in_player = false, _in_player = false,
_blocked = false,
_viscosity=0, -- Viscosity of node the arrow is currently in _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 _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) local function spawn_item(self, pos)
if not minetest.is_creative_enabled("") then if not minetest.is_creative_enabled("") then
local item = minetest.add_item(pos, "mcl_bows:arrow") 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()) item:set_yaw(self.object:get_yaw())
end end
mcl_burning.extinguish(self.object) mcl_burning.extinguish(self.object)
@ -94,12 +95,10 @@ local function damage_particles(pos, is_critical)
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = 15, amount = 15,
time = 0.1, time = 0.1,
minpos = {x=pos.x-0.5, y=pos.y-0.5, z=pos.z-0.5}, minpos = vector.offset(pos, -0.5, -0.5, -0.5),
maxpos = {x=pos.x+0.5, y=pos.y+0.5, z=pos.z+0.5}, maxpos = vector.offset(pos, 0.5, 0.5, 0.5),
minvel = {x=-0.1, y=-0.1, z=-0.1}, minvel = vector.new(-0.1, -0.1, -0.1),
maxvel = {x=0.1, y=0.1, z=0.1}, maxvel = vector.new(0.1, 0.1, 0.1),
minacc = {x=0, y=0, z=0},
maxacc = {x=0, y=0, z=0},
minexptime = 1, minexptime = 1,
maxexptime = 2, maxexptime = 2,
minsize = 1.5, minsize = 1.5,
@ -248,18 +247,19 @@ function ARROW_ENTITY.on_step(self, dtime)
-- Punch target object but avoid hurting enderman. -- Punch target object but avoid hurting enderman.
if not lua or lua.name ~= "mobs_mc:enderman" then 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) damage_particles(self.object:get_pos(), self._is_critical)
end end
if mcl_burning.is_burning(self.object) then if mcl_burning.is_burning(self.object) then
mcl_burning.set_on_fire(obj, 5) mcl_burning.set_on_fire(obj, 5)
end end
if self._in_player == false then if not self._in_player and not self._blocked then
obj:punch(self.object, 1.0, { obj:punch(self.object, 1.0, {
full_punch_interval=1.0, full_punch_interval=1.0,
damage_groups={fleshy=self._damage}, damage_groups={fleshy=self._damage},
}, self.object:get_velocity()) }, self.object:get_velocity())
if obj:is_player() then if obj:is_player() then
if not mcl_shields.is_blocking(obj) then
local placement local placement
self._placement = math.random(1, 2) self._placement = math.random(1, 2)
if self._placement == 1 then if self._placement == 1 then
@ -291,7 +291,15 @@ function ARROW_ENTITY.on_step(self, dtime)
end end
self._z_rotation = math.random(-30, 30) self._z_rotation = math.random(-30, 30)
self._y_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}) 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
self._blocked = true
self.object:set_velocity(vector.multiply(self.object:get_velocity(), -0.25))
end
minetest.after(150, function() minetest.after(150, function()
self.object:remove() self.object:remove()
end) end)
@ -301,7 +309,7 @@ function ARROW_ENTITY.on_step(self, dtime)
if is_player then 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 -- “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) minetest.sound_play({name="mcl_bows_hit_player", gain=0.1}, {to_player=self._shooter:get_player_name()}, true)
end end
@ -318,7 +326,8 @@ function ARROW_ENTITY.on_step(self, dtime)
end end
end 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) minetest.sound_play({name="mcl_bows_hit_other", gain=0.3}, {pos=self.object:get_pos(), max_hear_distance=16}, true)
end end
end end
@ -344,9 +353,9 @@ function ARROW_ENTITY.on_step(self, dtime)
local dir local dir
if math.abs(vel.y) < 0.00001 then if math.abs(vel.y) < 0.00001 then
if self._lastpos.y < pos.y then if self._lastpos.y < pos.y then
dir = {x=0, y=1, z=0} dir = vector.new(0, 1, 0)
else else
dir = {x=0, y=-1, z=0} dir = vector.new(0, -1, 0)
end end
else else
dir = minetest.facedir_to_dir(minetest.dir_to_facedir(minetest.yaw_to_dir(self.object:get_yaw()-YAW_OFFSET))) 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._stucktimer = 0
self._stuckrechecktimer = 0 self._stuckrechecktimer = 0
self.object:set_velocity({x=0, y=0, z=0}) self.object:set_velocity(vector.new(0, 0, 0))
self.object:set_acceleration({x=0, y=0, z=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) 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 end
-- Update internal variable -- Update internal variable
self._lastpos={x=pos.x, y=pos.y, z=pos.z} self._lastpos = pos
end end
-- Force recheck of stuck arrows when punched. -- Force recheck of stuck arrows when punched.

View File

@ -116,7 +116,7 @@ end
-- Bow item, uncharged state -- Bow item, uncharged state
minetest.register_tool("mcl_bows:crossbow", { minetest.register_tool("mcl_bows:crossbow", {
description = S("Corssbow"), description = S("Crossbow"),
_tt_help = S("Launches arrows"), _tt_help = S("Launches arrows"),
_doc_items_longdesc = S("Bows are ranged weapons to shoot arrows at your foes.").."\n".. _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."), 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", { minetest.register_tool("mcl_bows:crossbow_loaded", {
description = S("Corssbow"), description = S("Crossbow"),
_tt_help = S("Launches arrows"), _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."), 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, _doc_items_durability = BOW_DURABILITY,
inventory_image = "mcl_bows_crossbow_3.png", inventory_image = "mcl_bows_crossbow_3.png",
wield_scale = mcl_vars.tool_wield_scale, wield_scale = mcl_vars.tool_wield_scale,

View File

@ -1,6 +1,6 @@
name = mcl_bows name = mcl_bows
author = Arcelmi author = Arcelmi
description = This mod adds bows and arrows for MineClone 2. 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 optional_depends = awards, mcl_achievements, mcl_core, mcl_mobitems, playerphysics, doc, doc_identifier, mesecons_button

View File

@ -388,6 +388,7 @@ mcl_experience.register_on_add_xp(function(player, xp)
{list = "armor", index = 3}, {list = "armor", index = 3},
{list = "armor", index = 4}, {list = "armor", index = 4},
{list = "armor", index = 5}, {list = "armor", index = 5},
{list = "offhand", index = 1},
} }
local final_candidates = {} local final_candidates = {}

View File

@ -37,7 +37,7 @@ local lava_fire=
{ x = 1, y = 1, z = 0}, { x = 1, y = 1, z = 0},
{ x = 1, y = 1, z = 1} { x = 1, y = 1, z = 1}
} }
local alldirs= local adjacents =
{ {
{ x =-1, y = 0, z = 0}, { x =-1, y = 0, z = 0},
{ x = 1, y = 0, z = 0}, { x = 1, y = 0, z = 0},
@ -87,7 +87,7 @@ else
end end
local function fire_timer(pos) 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 end
local function spawn_fire(pos, age) 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}) minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z})
end 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", { minetest.register_node("mcl_fire:fire", {
description = S("Fire"), description = S("Fire"),
_doc_items_longdesc = fire_help, _doc_items_longdesc = fire_help,
@ -125,80 +142,12 @@ minetest.register_node("mcl_fire:fire", {
end end
end, end,
on_timer = function(pos) on_timer = function(pos)
local node = get_node(pos) local p=has_flammable(pos)
-- Age is a number from 0 to 15 and is increased every timer step. if not p or minetest.get_item_group(minetest.get_node(p).name, "flammable") == -1 then
-- "old" fire is more likely to be extinguished minetest.remove_node(pos)
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)
return return
end end
if age == 15 and not below_is_flammable then return true --restart timer
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)
end, end,
drop = "", drop = "",
sounds = {}, 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) minetest.sound_play("fire_extinguish_flame", {pos = pos, gain = 0.25, max_hear_distance = 16}, true)
end end
end, end,
on_timer = function(pos) -- light Nether portal (if possible)
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)
on_construct = function(pos) on_construct = function(pos)
fire_timer(pos)
if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time
mcl_portals.light_nether_portal(pos) mcl_portals.light_nether_portal(pos)
end end
@ -421,21 +349,39 @@ minetest.register_abm({
end, 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 function check_aircube(p1,p2)
local npos, node local nds=minetest.find_nodes_in_area(p1,p2,{"air"})
for n, v in ipairs(alldirs) do for k,v in pairs(nds) do
npos = vector.add(pos, v) if has_flammable(v) then return v end
node = get_node_or_nil(npos)
if node and node.name and get_item_group(node.name, "flammable") ~= 0 then
return npos
end
end end
return false return false
end 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 if not fire_enabled then
-- Occasionally remove fire if fire disabled -- Occasionally remove fire if fire disabled
@ -451,62 +397,70 @@ if not fire_enabled then
else -- Fire enabled 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 -- Set fire to air nodes
minetest.register_abm({ minetest.register_abm({
label = "Ignite fire by lava", label = "Ignite fire by lava",
nodenames = {"group:lava"}, nodenames = {"group:lava"},
neighbors = {"air"}, nodenames = {"mcl_core:lava_source","mcl_nether:nether_lava_source"},
neighbors = {"air","group:flammable"},
interval = 7, interval = 7,
chance = 3, chance = 3,
catch_up = false, catch_up = false,
action = function(pos) action = function(pos)
local i, dir, target, node, i2, f local p=get_ignitable_by_lava(pos)
i = math.random(1,9) if p then
dir = lava_fire[i] add_fire_particle(p,pos)
target = {x=pos.x+dir.x, y=pos.y+dir.y, z=pos.z+dir.z} spawn_fire(p)
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"
})
end end
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 end
-- Set pointed_thing on (normal) fire. -- Set pointed_thing on (normal) fire.

View File

@ -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)

View File

@ -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

View File

@ -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=

View File

@ -0,0 +1,3 @@
name = mcl_shields
author = NO11
depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics

View File

@ -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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -12,6 +12,14 @@ mcl_damage.register_modifier(function(obj, damage, reason)
local hp = obj:get_hp() local hp = obj:get_hp()
if hp - damage <= 0 then if hp - damage <= 0 then
local wield = obj:get_wielded_item() 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 if wield:get_name() == "mobs_mc:totem" then
local ppos = obj:get_pos() local ppos = obj:get_pos()
local pnname = minetest.get_node(ppos).name local pnname = minetest.get_node(ppos).name
@ -28,8 +36,13 @@ mcl_damage.register_modifier(function(obj, damage, reason)
if not minetest.is_creative_enabled(obj:get_player_name()) then if not minetest.is_creative_enabled(obj:get_player_name()) then
wield:take_item() wield:take_item()
if in_offhand then
obj:get_inventory():set_stack("offhand", 1, wield)
mcl_inventory.update_inventory_formspec(obj)
else
obj:set_wielded_item(wield) obj:set_wielded_item(wield)
end end
end
-- Effects -- Effects
minetest.sound_play({name = "mcl_totems_totem", gain = 1}, {pos=ppos, max_hear_distance = 16}, true) minetest.sound_play({name = "mcl_totems_totem", gain = 1}, {pos=ppos, max_hear_distance = 16}, true)

View File

@ -22,8 +22,10 @@ for _, action in pairs({"grant", "revoke"}) do
minetest["register_on_priv_" .. action](function(name, _, priv) minetest["register_on_priv_" .. action](function(name, _, priv)
if priv == "fly" then if priv == "fly" then
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
if player then
local meta = player:get_meta() local meta = player:get_meta()
meta:set_int("fly_changed", 1) meta:set_int("fly_changed", 1)
end end
end
end) end)
end end

View File

@ -9,7 +9,8 @@ local animation_blend = 0
local function get_mouse_button(player) local function get_mouse_button(player)
local controls = player:get_player_control() local controls = player:get_player_control()
local get_wielded_item_name = player:get_wielded_item():get_name() 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 return true
else else
return false return false
@ -188,6 +189,9 @@ minetest.register_globalstep(function(dtime)
animation_speed_mod = animation_speed_mod / 2 animation_speed_mod = animation_speed_mod / 2
end end
if mcl_shields.is_blocking(player) then
animation_speed_mod = animation_speed_mod / 2
end
-- ask if player is swiming -- 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.x < -0.35
or walking and velocity.z > 0.35 or walking and velocity.z > 0.35
or walking and velocity.z < -0.35 then 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 if player_sneak[name] ~= controls.sneak then
player_anim[name] = nil player_anim[name] = nil
player_sneak[name] = controls.sneak player_sneak[name] = controls.sneak
@ -212,9 +218,9 @@ minetest.register_globalstep(function(dtime)
player_set_animation(player, "swim_walk_mine", animation_speed_mod) player_set_animation(player, "swim_walk_mine", animation_speed_mod)
elseif not controls.sneak and head_in_water and is_sprinting == true then elseif not controls.sneak and head_in_water and is_sprinting == true then
player_set_animation(player, "swim_walk", animation_speed_mod) 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) 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) 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 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) player_set_animation(player, "run_walk_mine", animation_speed_mod)

View File

@ -336,8 +336,12 @@ minetest.register_globalstep(function(dtime)
player_velocity_old = player:get_velocity() or player:get_player_velocity() player_velocity_old = player:get_velocity() or player:get_player_velocity()
-- controls right and left arms pitch when shooting a bow -- controls right and left arms pitch when shooting a bow or blocking
if string.find(wielded:get_name(), "mcl_bows:bow") and control.RMB then 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_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)) 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 -- controls right and left arms pitch when holing a loaded crossbow

View File

@ -1,5 +1,5 @@
name = mcl_playerplus name = mcl_playerplus
author = TenPlus1 author = TenPlus1
description = Adds some simple player-related gameplay effects: Hurt by touching a cactus, suffocation and more. 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

View File

@ -6,7 +6,7 @@ mcl_wieldview = {
} }
function mcl_wieldview.get_item_texture(itemname) function mcl_wieldview.get_item_texture(itemname)
if itemname == "" then if itemname == "" or minetest.get_item_group(itemname, "no_wieldview") ~= 0 then
return return
end end
@ -41,14 +41,19 @@ function mcl_wieldview.update_wielded_item(player)
local def = mcl_wieldview.players[player] local def = mcl_wieldview.players[player]
if def.item == itemname then if def and (def.item == itemname) then
return return
end end
def.item = itemname local texture = mcl_wieldview.get_item_texture(itemname) or "blank.png"
def.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 end
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
@ -113,6 +118,10 @@ minetest.register_entity("mcl_wieldview:wieldnode", {
self.object:set_properties({textures = {""}}) self.object:set_properties({textures = {""}})
end end
if minetest.get_item_group(itemstring, "no_wieldview") ~= 0 then
self.object:set_properties({textures = {""}})
end
self.itemstring = itemstring self.itemstring = itemstring
end end
else else