Merge testing into production
|
@ -43,6 +43,7 @@
|
||||||
* Laurent Rocher
|
* Laurent Rocher
|
||||||
* Li0n
|
* Li0n
|
||||||
* Marcin Serwin
|
* Marcin Serwin
|
||||||
|
* Mental-Inferno
|
||||||
* Midgard
|
* Midgard
|
||||||
* MysticTempest
|
* MysticTempest
|
||||||
* Nicholas Niro
|
* Nicholas Niro
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ This mod adds mobs which closely resemble the mobs from the game Minecraft, vers
|
||||||
* [22i](https://github.com/22i): Models (done in Blender) and mob icons for spawn eggs
|
* [22i](https://github.com/22i): Models (done in Blender) and mob icons for spawn eggs
|
||||||
* [XSSheep](https://www.planetminecraft.com/member/xssheep/): Mob and item textures (from [Pixel Perfection](https://www.planetminecraft.com/texture_pack/131pixel-perfection/))
|
* [XSSheep](https://www.planetminecraft.com/member/xssheep/): Mob and item textures (from [Pixel Perfection](https://www.planetminecraft.com/texture_pack/131pixel-perfection/))
|
||||||
* MysticTempest: More mob textures
|
* MysticTempest: More mob textures
|
||||||
|
* [Mental-Inferno](https://github.com/Mental-Inferno): Code
|
||||||
* See `LICENSE_media.md` for detailed credits about each file
|
* See `LICENSE_media.md` for detailed credits about each file
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
mcl_mobs
|
mcl_mobs
|
||||||
|
mcl_potions
|
|
@ -76,7 +76,122 @@ local spider = {
|
||||||
}
|
}
|
||||||
mobs:register_mob("mobs_mc:spider", spider)
|
mobs:register_mob("mobs_mc:spider", spider)
|
||||||
|
|
||||||
-- Cave spider
|
|
||||||
|
|
||||||
|
--Cave Spider
|
||||||
|
|
||||||
|
local cave_spider = {
|
||||||
|
description = S("Cave Spider"),
|
||||||
|
type = "monster",
|
||||||
|
spawn_class = "hostile",
|
||||||
|
passive = false,
|
||||||
|
hostile = true,
|
||||||
|
always_climb = true,
|
||||||
|
docile_by_day = true,
|
||||||
|
rotate = 270,
|
||||||
|
|
||||||
|
--[[work-around for poison until punch augmentations are added to mob API
|
||||||
|
works functionally but the jump while punching animation in gone--]]
|
||||||
|
reach = 0.5, --makes it look like it's biting
|
||||||
|
attack_type = "projectile",
|
||||||
|
arrow = "spider_venom", --ultra short range projectile to inflict poison effect + punch damage
|
||||||
|
projectile_cooldown_min = 1,
|
||||||
|
projectile_cooldown_max = 1,
|
||||||
|
shoot_arrow = function(self, pos, dir)
|
||||||
|
local dmg = 2
|
||||||
|
mobs.shoot_projectile_handling("mobs_mc:spider_venom", pos, dir, self.object:get_yaw(), self.object, 1, dmg,nil,nil,nil,-0.6)
|
||||||
|
end,
|
||||||
|
|
||||||
|
hp_min = 12, --reflect Minecraft health
|
||||||
|
hp_max = 12,
|
||||||
|
ignores_cobwebs = true,
|
||||||
|
xp_min = 5,
|
||||||
|
xp_max = 5,
|
||||||
|
eye_height = 0.475,
|
||||||
|
armor = {fleshy = 100, arthropod = 100},
|
||||||
|
collisionbox = {-0.35, -0.01, -0.35, 0.35, 0.49, 0.35},
|
||||||
|
visual = "mesh",
|
||||||
|
mesh = "mobs_mc_spider.b3d",
|
||||||
|
textures = {
|
||||||
|
{"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"},
|
||||||
|
},
|
||||||
|
visual_size = {x=1.66666, y=1.5},
|
||||||
|
makes_footstep_sound = false,
|
||||||
|
sounds = {
|
||||||
|
random = "mobs_mc_spider_random",
|
||||||
|
attack = "mobs_mc_spider_attack",
|
||||||
|
damage = "mobs_mc_spider_hurt",
|
||||||
|
death = "mobs_mc_spider_death",
|
||||||
|
-- TODO: sounds: walk
|
||||||
|
distance = 16,
|
||||||
|
},
|
||||||
|
base_pitch = 1.25,
|
||||||
|
walk_velocity = 1.3,
|
||||||
|
run_velocity = 3.5, --Compenstaing for the loss of aility to leap while attacking
|
||||||
|
jump = true,
|
||||||
|
jump_height = 4,
|
||||||
|
view_range = 16,
|
||||||
|
floats = 1,
|
||||||
|
drops = {
|
||||||
|
{name = mobs_mc.items.string, chance = 1, min = 0, max = 2, looting = "common"},
|
||||||
|
{name = mobs_mc.items.spider_eye, chance = 3, min = 1, max = 1, looting = "common", looting_chance_function = function(lvl)
|
||||||
|
return 1 - 2 / (lvl + 3)
|
||||||
|
end},
|
||||||
|
},
|
||||||
|
specific_attack = { "player", "mobs_mc:iron_golem" },
|
||||||
|
fear_height = 4,
|
||||||
|
animation = {
|
||||||
|
stand_speed = 10,
|
||||||
|
walk_speed = 25,
|
||||||
|
run_speed = 50,
|
||||||
|
stand_start = 20,
|
||||||
|
stand_end = 40,
|
||||||
|
walk_start = 0,
|
||||||
|
walk_end = 20,
|
||||||
|
run_start = 0,
|
||||||
|
run_end = 20,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
mobs:register_mob("mobs_mc:cave_spider", cave_spider)
|
||||||
|
|
||||||
|
|
||||||
|
-- spider_venom (projectile)
|
||||||
|
mobs:register_arrow("mobs_mc:spider_venom", {
|
||||||
|
visual = "sprite",
|
||||||
|
visual_size = {x = 0.1, y = 0.1},
|
||||||
|
textures = {"hbhunger_icon_health_poison.png"},
|
||||||
|
velocity = 1,
|
||||||
|
collisionbox = {-.5, -.5, -.5, .5, .5, .5},
|
||||||
|
tail = 0,
|
||||||
|
|
||||||
|
hit_player = function(self, player)
|
||||||
|
player:punch(self.object, 1.0, {
|
||||||
|
full_punch_interval = 1.0,
|
||||||
|
damage_groups = {fleshy = self._damage},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
mcl_potions.poison_func(player, 0.5, 8) --modified cuz MC rate is an unessesarily bad fraction
|
||||||
|
local vel = player:get_velocity()
|
||||||
|
player:add_velocity({x=(vel.x * -1.5), y=6, z=(vel.z * -1.5)}) --"chaos knockback" effect (Temporary until I understand how to implement knockback for a projectile)
|
||||||
|
end,
|
||||||
|
|
||||||
|
hit_mob = function(self, mob)
|
||||||
|
if mob ~= self then --due to low power of attack, spider can shoot itself while chasing a target
|
||||||
|
mob:punch(self.object, 1.0, {
|
||||||
|
full_punch_interval = 1.0,
|
||||||
|
damage_groups = {fleshy = self._damage},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
if ((mob ~= "mobs_mc:cave_spider") and (mob ~= "mobs_mc:spider")) then --spider's don't have automatic immunity to poison yet so this is a stop gap solution
|
||||||
|
mcl_potions.poison_func(mob, 0.5, 8) --modified cuz MC rate is an unessesarily bad fraction
|
||||||
|
end
|
||||||
|
local vel = mob:get_velocity()
|
||||||
|
mob:add_velocity({x=(-1 * vel.z), y=6, z=(-1 * vel.x)}) --"chaos knockback" effect (Temporary until I understand how to implement knockback for a projectile)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
--[[ Cave spider (Previous code)
|
||||||
local cave_spider = table.copy(spider)
|
local cave_spider = table.copy(spider)
|
||||||
cave_spider.description = S("Cave Spider")
|
cave_spider.description = S("Cave Spider")
|
||||||
cave_spider.textures = { {"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"} }
|
cave_spider.textures = { {"mobs_mc_cave_spider.png^(mobs_mc_spider_eyes.png^[makealpha:0,0,0)"} }
|
||||||
|
@ -91,7 +206,7 @@ cave_spider.walk_velocity = 1.3
|
||||||
cave_spider.run_velocity = 3.2
|
cave_spider.run_velocity = 3.2
|
||||||
cave_spider.sounds = table.copy(spider.sounds)
|
cave_spider.sounds = table.copy(spider.sounds)
|
||||||
cave_spider.sounds.base_pitch = 1.25
|
cave_spider.sounds.base_pitch = 1.25
|
||||||
mobs:register_mob("mobs_mc:cave_spider", cave_spider)
|
mobs:register_mob("mobs_mc:cave_spider", cave_spider)--]]
|
||||||
|
|
||||||
|
|
||||||
mobs:spawn_specific(
|
mobs:spawn_specific(
|
||||||
|
|
|
@ -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")).."]"..
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = mcl_offhand
|
||||||
|
author = NO11
|
||||||
|
depends = mcl_inventory
|
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 168 B |
|
@ -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)
|
||||||
|
|
|
@ -544,6 +544,16 @@ for s=1, #specialstones do
|
||||||
clust_size = 3,
|
clust_size = 3,
|
||||||
y_min = mcl_vars.mg_nether_min,
|
y_min = mcl_vars.mg_nether_min,
|
||||||
y_max = mcl_vars.mg_nether_max,
|
y_max = mcl_vars.mg_nether_max,
|
||||||
|
noise_params = {
|
||||||
|
offset = 0,
|
||||||
|
scale = 1,
|
||||||
|
spread = {x=250, y=250, z=250},
|
||||||
|
seed = 12345,
|
||||||
|
octaves = 3,
|
||||||
|
persist = 0.6,
|
||||||
|
lacunarity = 2,
|
||||||
|
flags = "defaults",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
minetest.register_ore({
|
minetest.register_ore({
|
||||||
ore_type = "blob",
|
ore_type = "blob",
|
||||||
|
@ -554,6 +564,16 @@ for s=1, #specialstones do
|
||||||
clust_size = 5,
|
clust_size = 5,
|
||||||
y_min = mcl_vars.mg_nether_min,
|
y_min = mcl_vars.mg_nether_min,
|
||||||
y_max = mcl_vars.mg_nether_max,
|
y_max = mcl_vars.mg_nether_max,
|
||||||
|
noise_params = {
|
||||||
|
offset = 0,
|
||||||
|
scale = 1,
|
||||||
|
spread = {x=250, y=250, z=250},
|
||||||
|
seed = 12345,
|
||||||
|
octaves = 3,
|
||||||
|
persist = 0.6,
|
||||||
|
lacunarity = 2,
|
||||||
|
flags = "defaults",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 = {}
|
||||||
|
|
|
@ -0,0 +1,462 @@
|
||||||
|
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)
|
||||||
|
privs.interact = interact
|
||||||
|
minetest.set_player_privs(player_name, privs)
|
||||||
|
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
|
||||||
|
player:hud_set_flags({wielditem = true})
|
||||||
|
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)
|
|
@ -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
|
|
@ -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=
|
|
@ -0,0 +1,3 @@
|
||||||
|
name = mcl_shields
|
||||||
|
author = NO11
|
||||||
|
depends = mcl_damage, mcl_enchanting, mcl_banners, mcl_util, playerphysics
|
|
@ -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
|
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 639 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 4.3 KiB |
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -120,6 +120,114 @@ end
|
||||||
|
|
||||||
local node_stand, node_stand_below, node_head, node_feet
|
local node_stand, node_stand_below, node_head, node_feet
|
||||||
|
|
||||||
|
|
||||||
|
local function roundN(n, d)
|
||||||
|
if type(n) ~= "number" then return n end
|
||||||
|
local m = 10^d
|
||||||
|
return math.floor(n * m + 0.5) / m
|
||||||
|
end
|
||||||
|
|
||||||
|
local function close_enough(a,b)
|
||||||
|
local rt=true
|
||||||
|
if type(a) == "table" and type(b) == "table" then
|
||||||
|
for k,v in pairs(a) do
|
||||||
|
if roundN(v,2) ~= roundN(b[k],2) then
|
||||||
|
rt=false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
rt = roundN(a,2) == roundN(b,2)
|
||||||
|
end
|
||||||
|
return rt
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local function props_changed(props,oldprops)
|
||||||
|
local changed=false
|
||||||
|
local p={}
|
||||||
|
for k,v in pairs(props) do
|
||||||
|
if not close_enough(v,oldprops[k]) then
|
||||||
|
p[k]=v
|
||||||
|
changed=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return changed,p
|
||||||
|
end
|
||||||
|
|
||||||
|
--test if assert works
|
||||||
|
assert(true)
|
||||||
|
assert(not false)
|
||||||
|
|
||||||
|
--test data for == and ~=
|
||||||
|
local test_equal1=42
|
||||||
|
local test_equal2=42.0
|
||||||
|
local test_equal3=42.1
|
||||||
|
|
||||||
|
assert(test_equal1==test_equal1)
|
||||||
|
assert(test_equal1==test_equal2)
|
||||||
|
assert(test_equal1~=test_equal3)
|
||||||
|
|
||||||
|
--testdata for roundN
|
||||||
|
local test_round1=15
|
||||||
|
local test_round2=15.00199999999
|
||||||
|
local test_round3=15.00111111
|
||||||
|
local test_round4=15.00999999
|
||||||
|
|
||||||
|
assert(roundN(test_round1,2)==roundN(test_round1,2)) --test again if basic equality works because wth not
|
||||||
|
assert(roundN(test_round1,2)==roundN(test_round2,2))
|
||||||
|
assert(roundN(test_round1,2)==roundN(test_round3,2))
|
||||||
|
assert(roundN(test_round1,2)~=roundN(test_round4,2))
|
||||||
|
|
||||||
|
|
||||||
|
-- tests for close_enough
|
||||||
|
local test_cb = {-0.35,0,-0.35,0.35,0.8,0.35} --collisionboxes
|
||||||
|
local test_cb_close = {-0.351213,0,-0.35,0.35,0.8,0.351212}
|
||||||
|
local test_cb_diff = {-0.35,0,-1.35,0.35,0.8,0.35}
|
||||||
|
|
||||||
|
local test_eh = 1.65 --eye height
|
||||||
|
local test_eh_close = 1.65123123
|
||||||
|
local test_eh_diff = 1.35
|
||||||
|
|
||||||
|
local test_nt = { r = 225, b = 225, a = 225, g = 225 } --nametag
|
||||||
|
local test_nt_diff = { r = 225, b = 225, a = 0, g = 225 }
|
||||||
|
|
||||||
|
assert(close_enough(test_cb,test_cb_close))
|
||||||
|
assert(not close_enough(test_cb,test_cb_diff))
|
||||||
|
|
||||||
|
assert(close_enough(test_eh,test_eh_close))
|
||||||
|
assert(not close_enough(test_eh,test_eh_diff))
|
||||||
|
|
||||||
|
assert(not close_enough(test_nt,test_nt_diff)) --no floats involved here
|
||||||
|
|
||||||
|
--tests for props_changed
|
||||||
|
local test_properties_set1={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.65, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}
|
||||||
|
local test_properties_set2={collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 225, g = 225 }}
|
||||||
|
|
||||||
|
local test_p1,p=props_changed(test_properties_set1,test_properties_set1)
|
||||||
|
local test_p2,p=props_changed(test_properties_set1,test_properties_set2)
|
||||||
|
|
||||||
|
assert(not test_p1)
|
||||||
|
assert(test_p2)
|
||||||
|
|
||||||
|
-- we still don't really know if lua is lying to us! but at least everything *seems* to be ok
|
||||||
|
|
||||||
|
local function set_properties_conditional(player,props)
|
||||||
|
local changed,p=props_changed(props,player:get_properties())
|
||||||
|
if changed then
|
||||||
|
player:set_properties(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_bone_position_conditional(player,b,p,r) --bone,position,rotation
|
||||||
|
local oldp,oldr=player:get_bone_position(b)
|
||||||
|
if vector.equals(vector.round(oldp),vector.round(p)) and vector.equals(vector.round(oldr),vector.round(r)) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
player:set_bone_position(b,p,r)
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
|
|
||||||
time = time + dtime
|
time = time + dtime
|
||||||
|
@ -214,78 +322,82 @@ minetest.register_globalstep(function(dtime)
|
||||||
end
|
end
|
||||||
|
|
||||||
if wielded_def and wielded_def._mcl_toollike_wield then
|
if wielded_def and wielded_def._mcl_toollike_wield then
|
||||||
player:set_bone_position("Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0))
|
set_bone_position_conditional(player,"Wield_Item", vector.new(0,3.9,1.3), vector.new(90,0,0))
|
||||||
elseif string.find(wielded:get_name(), "mcl_bows:bow") then
|
elseif string.find(wielded:get_name(), "mcl_bows:bow") then
|
||||||
player:set_bone_position("Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20))
|
set_bone_position_conditional(player,"Wield_Item", vector.new(.5,4.5,-1.6), vector.new(90,0,20))
|
||||||
elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then
|
elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then
|
||||||
player:set_bone_position("Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(64,90,0))
|
set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(64,90,0))
|
||||||
elseif string.find(wielded:get_name(), "mcl_bows:crossbow") then
|
elseif string.find(wielded:get_name(), "mcl_bows:crossbow") then
|
||||||
player:set_bone_position("Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(90,90,0))
|
set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,5.7,1.8), vector.new(90,90,0))
|
||||||
else
|
else
|
||||||
player:set_bone_position("Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
|
set_bone_position_conditional(player,"Wield_Item", vector.new(-1.5,4.9,1.8), vector.new(135,0,90))
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
||||||
player:set_bone_position("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(20, -20, 0))
|
||||||
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3.5,5.785,0), vector.new(pitch+90,43,pitch * .35))
|
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
|
-- controls right and left arms pitch when holing a loaded crossbow
|
||||||
elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then
|
elseif string.find(wielded:get_name(), "mcl_bows:crossbow_loaded") then
|
||||||
player:set_bone_position("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))
|
||||||
player:set_bone_position("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 loading a crossbow
|
-- controls right and left arms pitch when loading a crossbow
|
||||||
elseif string.find(wielded:get_name(), "mcl_bows:crossbow_") then
|
elseif string.find(wielded:get_name(), "mcl_bows:crossbow_") then
|
||||||
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(45,-20,25))
|
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(45,-20,25))
|
||||||
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(55,20,-45))
|
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(55,20,-45))
|
||||||
-- when punching
|
-- when punching
|
||||||
elseif control.LMB and not parent then
|
elseif control.LMB and not parent then
|
||||||
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0))
|
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(pitch,0,0))
|
||||||
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
|
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
|
||||||
-- when holding an item.
|
-- when holding an item.
|
||||||
elseif wielded:get_name() ~= "" then
|
elseif wielded:get_name() ~= "" then
|
||||||
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(20,0,0))
|
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(20,0,0))
|
||||||
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
|
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
|
||||||
-- resets arms pitch
|
-- resets arms pitch
|
||||||
else
|
else
|
||||||
player:set_bone_position("Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
|
set_bone_position_conditional(player,"Arm_Left_Pitch_Control", vector.new(3,5.785,0), vector.new(0,0,0))
|
||||||
player:set_bone_position("Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0))
|
set_bone_position_conditional(player,"Arm_Right_Pitch_Control", vector.new(-3,5.785,0), vector.new(0,0,0))
|
||||||
end
|
end
|
||||||
|
|
||||||
if elytra.active then
|
if elytra.active then
|
||||||
-- set head pitch and yaw when flying
|
-- set head pitch and yaw when flying
|
||||||
player:set_bone_position("Head_Control", vector.new(0,6.3,0), vector.new(pitch-degrees(dir_to_pitch(player_velocity)),player_vel_yaw - yaw,0))
|
set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch-degrees(dir_to_pitch(player_velocity)),player_vel_yaw - yaw,0))
|
||||||
-- sets eye height, and nametag color accordingly
|
-- sets eye height, and nametag color accordingly
|
||||||
player:set_properties({collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
set_properties_conditional(player,{collisionbox = {-0.35,0,-0.35,0.35,0.8,0.35}, eye_height = 0.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
||||||
-- control body bone when flying
|
-- control body bone when flying
|
||||||
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(degrees(dir_to_pitch(player_velocity)) - 90,-player_vel_yaw + yaw + 180,0))
|
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(degrees(dir_to_pitch(player_velocity)) - 90,-player_vel_yaw + yaw + 180,0))
|
||||||
elseif parent then
|
elseif parent then
|
||||||
local parent_yaw = degrees(parent:get_yaw())
|
local parent_yaw = degrees(parent:get_yaw())
|
||||||
player:set_properties({collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
||||||
player:set_bone_position("Head_Control", vector.new(0,6.3,0), vector.new(pitch, -limit_vel_yaw(yaw, parent_yaw) + parent_yaw, 0))
|
set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch, -limit_vel_yaw(yaw, parent_yaw) + parent_yaw, 0))
|
||||||
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
|
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0,0,0))
|
||||||
elseif control.sneak then
|
elseif control.sneak then
|
||||||
-- controls head pitch when sneaking
|
-- controls head pitch when sneaking
|
||||||
player:set_bone_position("Head_Control", vector.new(0,6.3,0), vector.new(pitch, player_vel_yaw - yaw, player_vel_yaw - yaw))
|
set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch, player_vel_yaw - yaw, player_vel_yaw - yaw))
|
||||||
-- sets eye height, and nametag color accordingly
|
-- sets eye height, and nametag color accordingly
|
||||||
player:set_properties({collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 0, g = 225 }})
|
set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.35, nametag_color = { r = 225, b = 225, a = 0, g = 225 }})
|
||||||
-- sneaking body conrols
|
-- sneaking body conrols
|
||||||
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0, -player_vel_yaw + yaw, 0))
|
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0, -player_vel_yaw + yaw, 0))
|
||||||
elseif get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 and is_sprinting(name) == true then
|
elseif get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 and is_sprinting(name) == true then
|
||||||
-- set head pitch and yaw when swimming
|
-- set head pitch and yaw when swimming
|
||||||
player:set_bone_position("Head_Control", vector.new(0,6.3,0), vector.new(pitch-degrees(dir_to_pitch(player_velocity)),player_vel_yaw - yaw,0))
|
set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch-degrees(dir_to_pitch(player_velocity)),player_vel_yaw - yaw,0))
|
||||||
-- sets eye height, and nametag color accordingly
|
-- sets eye height, and nametag color accordingly
|
||||||
player:set_properties({collisionbox = {-0.312,0,-0.312,0.312,0.8,0.312}, eye_height = 0.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,0.8,0.312}, eye_height = 0.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
||||||
-- control body bone when swimming
|
-- control body bone when swimming
|
||||||
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(degrees(dir_to_pitch(player_velocity)) - 90,-player_vel_yaw + yaw + 180,0))
|
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(degrees(dir_to_pitch(player_velocity)) - 90,-player_vel_yaw + yaw + 180,0))
|
||||||
else
|
else
|
||||||
-- sets eye height, and nametag color accordingly
|
-- sets eye height, and nametag color accordingly
|
||||||
player:set_properties({collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
set_properties_conditional(player,{collisionbox = {-0.312,0,-0.312,0.312,1.8,0.312}, eye_height = 1.5, nametag_color = { r = 225, b = 225, a = 225, g = 225 }})
|
||||||
|
|
||||||
player:set_bone_position("Head_Control", vector.new(0,6.3,0), vector.new(pitch, player_vel_yaw - yaw, 0))
|
set_bone_position_conditional(player,"Head_Control", vector.new(0,6.3,0), vector.new(pitch, player_vel_yaw - yaw, 0))
|
||||||
player:set_bone_position("Body_Control", vector.new(0,6.3,0), vector.new(0, -player_vel_yaw + yaw, 0))
|
set_bone_position_conditional(player,"Body_Control", vector.new(0,6.3,0), vector.new(0, -player_vel_yaw + yaw, 0))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update jump status immediately since we need this info in real time.
|
-- Update jump status immediately since we need this info in real time.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Status Effect Refresh for Mineclone 5
|
||||||
|
|
||||||
|
This allows the use of status effect function from mcl_potions and prevents them
|
||||||
|
from continuing their effect after player respawn
|
||||||
|
|
||||||
|
## Licensing
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Mental-Inferno
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
minetest.register_on_respawnplayer(function(player)
|
||||||
|
mcl_potions._reset_player_effects(player, true)
|
||||||
|
end)
|
|
@ -0,0 +1,4 @@
|
||||||
|
name = mcl_refresh_status
|
||||||
|
author = Mental-Inferno
|
||||||
|
description = Resets status-effects inflicted on player when player respawns
|
||||||
|
depends = mcl_potions
|
|
@ -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
|
||||||
|
|