Merge pull request 'Armor wearing mobs' (#285) from MrRar/MineClone5:zarmor into master

Reviewed-on: MineClone5/MineClone5#285
This commit is contained in:
commit d0fcab11e9
4 changed files with 114 additions and 1 deletions

View File

@ -227,6 +227,11 @@ functions needed for the mob to work properly which contains the following:
older mobs. older mobs.
'pushable' Allows players, & other mobs to push the mob. 'pushable' Allows players, & other mobs to push the mob.
'spawn_with_armor' If set to true, the mob has a small chance of spawning with
random matched armor. If set to a string, the string represents
the material type of the armor. Any materials used by
mcl_armor will work. Example: "gold"
It is assumed that the first texture is for armor.
MineClone 2 extensions: MineClone 2 extensions:

View File

@ -375,6 +375,7 @@ function mobs:register_mob(name, def)
--moves the wrong way --moves the wrong way
swap_y_with_x = def.swap_y_with_x or false, swap_y_with_x = def.swap_y_with_x or false,
reverse_head_yaw = def.reverse_head_yaw or false, reverse_head_yaw = def.reverse_head_yaw or false,
_spawn_with_armor = def.spawn_with_armor,
--END HEAD CODE VARIABLES --END HEAD CODE VARIABLES

View File

@ -13,8 +13,13 @@ mobs.can_despawn = function(self)
if self.tamed or self.bred or self.nametag then return false end if self.tamed or self.bred or self.nametag then return false end
local mob_pos = self.object:get_pos() local mob_pos = self.object:get_pos()
if not mob_pos then return true end if not mob_pos then return true end
local players = minetest_get_connected_players()
if #players == 0 then return false end
-- If no players, probably this is being called from get_staticdata() at server shutdown time
-- Minetest is to buggy (as of 5.5) to delete entities at server shutdown time anyway
local distance = 999 local distance = 999
for _, player in pairs(minetest_get_connected_players()) do for _, player in pairs(players) do
if player and player:get_hp() > 0 then if player and player:get_hp() > 0 then
local player_pos = player:get_pos() local player_pos = player:get_pos()
local new_distance = vector_distance(player_pos, mob_pos) local new_distance = vector_distance(player_pos, mob_pos)
@ -62,6 +67,102 @@ mobs.mob_staticdata = function(self)
return minetest.serialize(tmp) return minetest.serialize(tmp)
end end
mobs.armor_setup = function(self)
if not self._armor_items then
local armor = {}
-- Source: https://minecraft.fandom.com/wiki/Zombie
local materials = {
{name = "leather", chance = 0.3706},
{name = "gold", chance = 0.4873},
{name = "chain", chance = 0.129},
{name = "iron", chance = 0.0127},
{name = "diamond", chance = 0.0004}
}
local types = {
{name = "helmet", chance = 0.15},
{name = "chestplate", chance = 0.75},
{name = "leggings", chance = 0.75},
{name = "boots", chance = 0.75}
}
local material
if type(self._spawn_with_armor) == "string" then
material = self._spawn_with_armor
else
local chance = 0
for i, m in pairs(materials) do
chance = chance + m.chance
if math.random() <= chance then
material = m.name
break
end
end
end
for i, t in pairs(types) do
if math.random() <= t.chance then
armor[t.name] = material
else
break
end
end
-- Save armor items in lua entity
self._armor_items = {}
for atype, material in pairs(armor) do
local item = "mcl_armor:" .. atype .. "_" .. material
self._armor_items[atype] = item
end
-- Setup armor drops
for atype, material in pairs(armor) do
local wear = math.random(1, 65535)
local item = "mcl_armor:" .. atype .. "_" .. material .. " 1 " .. wear
self.drops = table.copy(self.drops)
table.insert(self.drops, {
name = item,
chance = 1/0.085, -- 8.5%
min = 1,
max = 1,
looting = "rare",
looting_factor = 0.01 / 3,
})
end
-- Configure textures
local t = ""
local first_image = true
for atype, material in pairs(armor) do
if not first_image then
t = t .. "^"
end
t = t .. "mcl_armor_" .. atype .. "_" .. material .. ".png"
first_image = false
end
if t ~= "" then
self.base_texture = table.copy(self.base_texture)
self.base_texture[1] = t
end
-- Configure damage groups based on armor
-- Source: https://minecraft.fandom.com/wiki/Armor#Armor_points
local points = 2
for atype, material in pairs(armor) do
local item_name = "mcl_armor:" .. atype .. "_" .. material
points = points + minetest.get_item_group(item_name, "mcl_armor_points")
end
local armor_strength = 100 - 4 * points
local armor_groups = self.object:get_armor_groups()
armor_groups.fleshy = armor_strength
self.armor = armor_groups
-- Helmet protects mob from sun damage
if armor.helmet then
self.ignited_by_sunlight = false
end
end
end
-- activate mob and reload settings -- activate mob and reload settings
mobs.mob_activate = function(self, staticdata, def, dtime) mobs.mob_activate = function(self, staticdata, def, dtime)
@ -104,6 +205,11 @@ mobs.mob_activate = function(self, staticdata, def, dtime)
self.base_colbox = self.collisionbox self.base_colbox = self.collisionbox
self.base_selbox = self.selectionbox self.base_selbox = self.selectionbox
end end
-- Setup armor on mobs
if self._spawn_with_armor then
mobs.armor_setup(self)
end
-- for current mobs that dont have this set -- for current mobs that dont have this set
if not self.base_selbox then if not self.base_selbox then

View File

@ -204,6 +204,7 @@ local zombie = {
attack_type = "punch", attack_type = "punch",
punch_timer_cooloff = 0.5, punch_timer_cooloff = 0.5,
harmed_by_heal = true, harmed_by_heal = true,
spawn_with_armor = true,
} }
mobs:register_mob("mobs_mc:zombie", zombie) mobs:register_mob("mobs_mc:zombie", zombie)