Merge pull request 'Villager employment system and mob-api enhancements' (#2209) from villagers_jobsites into master
Reviewed-on: https://git.minetest.land/MineClone2/MineClone2/pulls/2209
@ -1438,6 +1438,7 @@ end
|
|||||||
|
|
||||||
-- should mob follow what I'm holding ?
|
-- should mob follow what I'm holding ?
|
||||||
local follow_holding = function(self, clicker)
|
local follow_holding = function(self, clicker)
|
||||||
|
if self.nofollow then return false end
|
||||||
|
|
||||||
if mobs.invis[clicker:get_player_name()] then
|
if mobs.invis[clicker:get_player_name()] then
|
||||||
return false
|
return false
|
||||||
@ -2317,17 +2318,50 @@ local dogswitch = function(self, dtime)
|
|||||||
return self.dogshoot_switch
|
return self.dogshoot_switch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function go_to_pos(entity,b)
|
||||||
|
if not entity then return end
|
||||||
|
local s=entity.object:get_pos()
|
||||||
|
if vector.distance(b,s) < 1 then
|
||||||
|
--set_velocity(entity,0)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
local v = { x = b.x - s.x, z = b.z - s.z }
|
||||||
|
local yaw = (math.atan(v.z / v.x) + math.pi / 2) - entity.rotate
|
||||||
|
if b.x > s.x then yaw = yaw + math.pi end
|
||||||
|
entity.object:set_yaw(yaw)
|
||||||
|
set_velocity(entity,entity.follow_velocity)
|
||||||
|
mobs:set_animation(entity, "walk")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_doors(self)
|
||||||
|
local p = self.object:get_pos()
|
||||||
|
local t = minetest.get_timeofday()
|
||||||
|
local dd = minetest.find_nodes_in_area(vector.offset(p,-1,-1,-1),vector.offset(p,1,1,1),{"group:door"})
|
||||||
|
for _,d in pairs(dd) do
|
||||||
|
local n = minetest.get_node(d)
|
||||||
|
if n.name:find("_b_") then
|
||||||
|
local def = minetest.registered_nodes[n.name]
|
||||||
|
local closed = n.name:find("_b_1")
|
||||||
|
if t < 0.3 or t > 0.8 then
|
||||||
|
if not closed then def.on_rightclick(d,n,self) end
|
||||||
|
else
|
||||||
|
if closed then def.on_rightclick(d,n,self) end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- execute current state (stand, walk, run, attacks)
|
-- execute current state (stand, walk, run, attacks)
|
||||||
-- returns true if mob has died
|
-- returns true if mob has died
|
||||||
local do_states = function(self, dtime)
|
local do_states = function(self, dtime)
|
||||||
|
if self.can_open_doors then check_doors(self) end
|
||||||
|
|
||||||
local yaw = self.object:get_yaw() or 0
|
local yaw = self.object:get_yaw() or 0
|
||||||
|
|
||||||
if self.state == "stand" then
|
if self.state == "stand" then
|
||||||
|
|
||||||
if random(1, 4) == 1 then
|
if random(1, 4) == 1 then
|
||||||
|
|
||||||
local lp = nil
|
|
||||||
local s = self.object:get_pos()
|
local s = self.object:get_pos()
|
||||||
local objs = minetest.get_objects_inside_radius(s, 3)
|
local objs = minetest.get_objects_inside_radius(s, 3)
|
||||||
|
|
||||||
@ -2340,7 +2374,7 @@ local do_states = function(self, dtime)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- look at any players nearby, otherwise turn randomly
|
-- look at any players nearby, otherwise turn randomly
|
||||||
if lp then
|
if self.look_at_players then
|
||||||
|
|
||||||
local vec = {
|
local vec = {
|
||||||
x = lp.x - s.x,
|
x = lp.x - s.x,
|
||||||
@ -2375,8 +2409,35 @@ local do_states = function(self, dtime)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif self.state == "walk" then
|
elseif self.state == "gowp" then
|
||||||
|
local p = self.object:get_pos()
|
||||||
|
if not p or not self._target then return end
|
||||||
|
if vector.distance(p,self._target) < 2 or ( self.waypoints and #self.waypoints == 0 ) then
|
||||||
|
self.waypoints = nil
|
||||||
|
self._target = nil
|
||||||
|
self.current_target = nil
|
||||||
|
self.state = "walk"
|
||||||
|
if self.callback_arrived then return self.callback_arrived(self) end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if self.waypoints and ( not self.current_target or vector.distance(p,self.current_target) < 1.5 ) then
|
||||||
|
self.current_target = table.remove(self.waypoints, 1)
|
||||||
|
--minetest.log("nextwp:".. tostring(self.current_target) )
|
||||||
|
elseif self.current_target then
|
||||||
|
go_to_pos(self,self.current_target)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.current_target and not minetest.line_of_sight(self.object:get_pos(),self.current_target) then
|
||||||
|
self.waypoints=minetest.find_path(p,self._target,150,1,4)
|
||||||
|
self.current_target = nil
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not self.current_target then
|
||||||
|
--minetest.log("no path")
|
||||||
|
self.state = "walk"
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif self.state == "walk" then
|
||||||
local s = self.object:get_pos()
|
local s = self.object:get_pos()
|
||||||
local lp = nil
|
local lp = nil
|
||||||
|
|
||||||
@ -2880,6 +2941,62 @@ local do_states = function(self, dtime)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local plane_adjacents = {
|
||||||
|
vector.new(1,0,0),
|
||||||
|
vector.new(-1,0,0),
|
||||||
|
vector.new(0,0,1),
|
||||||
|
vector.new(0,0,-1),
|
||||||
|
}
|
||||||
|
|
||||||
|
function mobs:gopath(self,target,callback_arrived)
|
||||||
|
local p = self.object:get_pos()
|
||||||
|
local t = vector.offset(target,0,1,0)
|
||||||
|
local wp = minetest.find_path(p,t,150,1,4)
|
||||||
|
if not wp then
|
||||||
|
local d = minetest.find_node_near(target,16,{"group:door"})
|
||||||
|
if d then
|
||||||
|
for _,v in pairs(plane_adjacents) do
|
||||||
|
local pos = vector.add(d,v)
|
||||||
|
local n = minetest.get_node(pos)
|
||||||
|
if n.name == "air" then
|
||||||
|
wp = minetest.find_path(p,pos,150,1,4)
|
||||||
|
if wp then break end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if wp and #wp > 0 then
|
||||||
|
self._target = t
|
||||||
|
self.callback_arrived = callback_arrived
|
||||||
|
self.waypoints = wp
|
||||||
|
self.state = "gowp"
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
--minetest.log("no path found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function player_near(pos)
|
||||||
|
for _,o in pairs(minetest.get_objects_inside_radius(pos,2)) do
|
||||||
|
if o:is_player() then return true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function check_item_pickup(self)
|
||||||
|
if self.pick_up and #self.pick_up > 0 then
|
||||||
|
local p = self.object:get_pos()
|
||||||
|
for _,o in pairs(minetest.get_objects_inside_radius(p,2)) do
|
||||||
|
local l=o:get_luaentity()
|
||||||
|
if l and l.name == "__builtin:item" then
|
||||||
|
for k,v in pairs(self.pick_up) do
|
||||||
|
if not player_near(p) and self.on_pick_up and l.itemstring:find(v) then
|
||||||
|
if self.on_pick_up(self,l) == nil then o:remove() end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- falling and fall damage
|
-- falling and fall damage
|
||||||
-- returns true if mob died
|
-- returns true if mob died
|
||||||
@ -3481,7 +3598,7 @@ end
|
|||||||
|
|
||||||
-- main mob function
|
-- main mob function
|
||||||
local mob_step = function(self, dtime)
|
local mob_step = function(self, dtime)
|
||||||
|
check_item_pickup(self)
|
||||||
if not self.fire_resistant then
|
if not self.fire_resistant then
|
||||||
mcl_burning.tick(self.object, dtime, self)
|
mcl_burning.tick(self.object, dtime, self)
|
||||||
end
|
end
|
||||||
@ -3576,8 +3693,7 @@ local mob_step = function(self, dtime)
|
|||||||
-- attack timer
|
-- attack timer
|
||||||
self.timer = self.timer + dtime
|
self.timer = self.timer + dtime
|
||||||
|
|
||||||
if self.state ~= "attack" then
|
if self.state ~= "attack" and self.state ~= "gowp" then
|
||||||
|
|
||||||
if self.timer < 1 then
|
if self.timer < 1 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -3845,6 +3961,8 @@ minetest.register_entity(name, {
|
|||||||
sounds = def.sounds or {},
|
sounds = def.sounds or {},
|
||||||
animation = def.animation,
|
animation = def.animation,
|
||||||
follow = def.follow,
|
follow = def.follow,
|
||||||
|
nofollow = def.nofollow,
|
||||||
|
can_open_doors = def.can_open_doors,
|
||||||
jump = def.jump ~= false,
|
jump = def.jump ~= false,
|
||||||
walk_chance = def.walk_chance or 50,
|
walk_chance = def.walk_chance or 50,
|
||||||
attacks_monsters = def.attacks_monsters or false,
|
attacks_monsters = def.attacks_monsters or false,
|
||||||
@ -3911,6 +4029,7 @@ minetest.register_entity(name, {
|
|||||||
texture_mods = {},
|
texture_mods = {},
|
||||||
shoot_arrow = def.shoot_arrow,
|
shoot_arrow = def.shoot_arrow,
|
||||||
sounds_child = def.sounds_child,
|
sounds_child = def.sounds_child,
|
||||||
|
pick_up = def.pick_up,
|
||||||
explosion_strength = def.explosion_strength,
|
explosion_strength = def.explosion_strength,
|
||||||
suffocation_timer = 0,
|
suffocation_timer = 0,
|
||||||
follow_velocity = def.follow_velocity or 2.4,
|
follow_velocity = def.follow_velocity or 2.4,
|
||||||
@ -3934,6 +4053,8 @@ minetest.register_entity(name, {
|
|||||||
|
|
||||||
on_grown = def.on_grown,
|
on_grown = def.on_grown,
|
||||||
|
|
||||||
|
on_pick_up = def.on_pick_up,
|
||||||
|
|
||||||
on_detach_child = mob_detach_child,
|
on_detach_child = mob_detach_child,
|
||||||
|
|
||||||
on_activate = function(self, staticdata, dtime)
|
on_activate = function(self, staticdata, dtime)
|
||||||
@ -4250,7 +4371,7 @@ function mobs:feed_tame(self, clicker, feed_count, breed, tame)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- can eat/tame with item in hand
|
-- can eat/tame with item in hand
|
||||||
if follow_holding(self, clicker) then
|
if self.nofollow or follow_holding(self, clicker) then
|
||||||
|
|
||||||
-- if not in creative then take item
|
-- if not in creative then take item
|
||||||
if not mobs.is_creative(clicker:get_player_name()) then
|
if not mobs.is_creative(clicker:get_player_name()) then
|
||||||
|
@ -194,6 +194,7 @@ functions needed for the mob to work properly which contains the following:
|
|||||||
'punch2' animations.
|
'punch2' animations.
|
||||||
|
|
||||||
'animation' holds a table containing animation names and settings for use with mesh models:
|
'animation' holds a table containing animation names and settings for use with mesh models:
|
||||||
|
{
|
||||||
'stand_start'start frame for when mob stands still.
|
'stand_start'start frame for when mob stands still.
|
||||||
'stand_end' end frame of stand animation.
|
'stand_end' end frame of stand animation.
|
||||||
'stand_speed'speed of animation in frames per second.
|
'stand_speed'speed of animation in frames per second.
|
||||||
@ -219,6 +220,7 @@ functions needed for the mob to work properly which contains the following:
|
|||||||
'die_end'
|
'die_end'
|
||||||
'die_speed'
|
'die_speed'
|
||||||
'die_loop' when set to false stops the animation looping.
|
'die_loop' when set to false stops the animation looping.
|
||||||
|
}
|
||||||
|
|
||||||
Using '_loop = false' setting will stop any of the above animations from
|
Using '_loop = false' setting will stop any of the above animations from
|
||||||
looping.
|
looping.
|
||||||
@ -237,7 +239,7 @@ functions needed for the mob to work properly which contains the following:
|
|||||||
'rain_damage' damage per second if mob is standing in rain (default: 0)
|
'rain_damage' damage per second if mob is standing in rain (default: 0)
|
||||||
'sunlight_damage' holds the damage per second inflicted to mobs when they
|
'sunlight_damage' holds the damage per second inflicted to mobs when they
|
||||||
are in direct sunlight
|
are in direct sunlight
|
||||||
'spawn_small_alternative': name of a smaller mob to use as replacement if
|
'spawn_small_alternative' name of a smaller mob to use as replacement if
|
||||||
spawning fails due to space requirements
|
spawning fails due to space requirements
|
||||||
'glow' same as in entity definition
|
'glow' same as in entity definition
|
||||||
'child' if true, spawn mob as child
|
'child' if true, spawn mob as child
|
||||||
@ -253,6 +255,12 @@ functions needed for the mob to work properly which contains the following:
|
|||||||
'fire_resistant' If true, the mob can't burn
|
'fire_resistant' If true, the mob can't burn
|
||||||
'fire_damage_resistant' If true the mob will not take damage when burning
|
'fire_damage_resistant' If true the mob will not take damage when burning
|
||||||
'ignited_by_sunlight' If true the mod will burn at daytime. (Takes sunlight_damage per second)
|
'ignited_by_sunlight' If true the mod will burn at daytime. (Takes sunlight_damage per second)
|
||||||
|
'nofollow' Do not follow players when they wield the "follow" item. For mobs (like villagers)
|
||||||
|
that are bred in a different way.
|
||||||
|
'pick_up' table of itemstrings the mob will pick up (e.g. for breeding)
|
||||||
|
'on_pick_up' function that will be called on item pickup - return true to not pickup the item
|
||||||
|
|
||||||
|
mobs:gopath(self,target,callback_arrived) pathfind a way to target and run callback on arrival
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ mobs_mc.follow = {
|
|||||||
dog = { mobs_mc.items.rabbit_raw, mobs_mc.items.rabbit_cooked, mobs_mc.items.mutton_raw, mobs_mc.items.mutton_cooked, mobs_mc.items.beef_raw, mobs_mc.items.beef_cooked, mobs_mc.items.chicken_raw, mobs_mc.items.chicken_cooked, mobs_mc.items.rotten_flesh,
|
dog = { mobs_mc.items.rabbit_raw, mobs_mc.items.rabbit_cooked, mobs_mc.items.mutton_raw, mobs_mc.items.mutton_cooked, mobs_mc.items.beef_raw, mobs_mc.items.beef_cooked, mobs_mc.items.chicken_raw, mobs_mc.items.chicken_cooked, mobs_mc.items.rotten_flesh,
|
||||||
-- Mobs Redo items
|
-- Mobs Redo items
|
||||||
"mobs:meat", "mobs:meat_raw" },
|
"mobs:meat", "mobs:meat_raw" },
|
||||||
villager = { "mcl_farming:bread" },
|
villager = { "mcl_farming:bread", "mcl_farming:carrot_item", "mcl_farming:beetroot_item" , "mcl_farming:potato_item" },
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Contents for replace_what
|
-- Contents for replace_what
|
||||||
|
@ -9,7 +9,7 @@ local S = minetest.get_translator("mobs_mc")
|
|||||||
--################### IRON GOLEM
|
--################### IRON GOLEM
|
||||||
--###################
|
--###################
|
||||||
|
|
||||||
|
local etime = 0
|
||||||
|
|
||||||
mobs:register_mob("mobs_mc:iron_golem", {
|
mobs:register_mob("mobs_mc:iron_golem", {
|
||||||
description = S("Iron Golem"),
|
description = S("Iron Golem"),
|
||||||
@ -41,6 +41,26 @@ mobs:register_mob("mobs_mc:iron_golem", {
|
|||||||
group_attack = true,
|
group_attack = true,
|
||||||
attacks_monsters = true,
|
attacks_monsters = true,
|
||||||
attack_type = "dogfight",
|
attack_type = "dogfight",
|
||||||
|
_got_poppy = false,
|
||||||
|
pick_up = {"mcl_flowers:poppy"},
|
||||||
|
on_pick_up = function(self,n)
|
||||||
|
if n.itemstring:find("mcl_flowers:poppy") then
|
||||||
|
if not self._got_poppy then
|
||||||
|
self._got_poppy=true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
replace_what = {"mcl_flowers:poppy"},
|
||||||
|
replace_with = {"air"},
|
||||||
|
on_replace = function(self, pos, oldnode, newnode)
|
||||||
|
if not self.got_poppy and oldnode.name == "mcl_flowers:poppy" then
|
||||||
|
self._got_poppy=true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end,
|
||||||
drops = {
|
drops = {
|
||||||
{name = mobs_mc.items.iron_ingot,
|
{name = mobs_mc.items.iron_ingot,
|
||||||
chance = 1,
|
chance = 1,
|
||||||
@ -60,6 +80,14 @@ mobs:register_mob("mobs_mc:iron_golem", {
|
|||||||
punch_start = 40, punch_end = 50,
|
punch_start = 40, punch_end = 50,
|
||||||
},
|
},
|
||||||
jump = true,
|
jump = true,
|
||||||
|
on_step = function(self,dtime)
|
||||||
|
etime = etime + dtime
|
||||||
|
if etime > 10 then
|
||||||
|
if self._home and vector.distance(self._home,self.object:get_pos()) > 50 then
|
||||||
|
mobs:gopath(self,self._home)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_armorer.png
Normal file
After Width: | Height: | Size: 971 B |
Before Width: | Height: | Size: 866 B After Width: | Height: | Size: 989 B |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_cartographer.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 1.1 KiB |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_fisherman.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_fletcher.png
Normal file
After Width: | Height: | Size: 950 B |
After Width: | Height: | Size: 933 B |
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 1.1 KiB |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_nitwit.png
Normal file
After Width: | Height: | Size: 1008 B |
Before Width: | Height: | Size: 768 B After Width: | Height: | Size: 921 B |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_sheperd.png
Normal file
After Width: | Height: | Size: 983 B |
Before Width: | Height: | Size: 866 B After Width: | Height: | Size: 941 B |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_toolsmith.png
Normal file
After Width: | Height: | Size: 964 B |
BIN
mods/ENTITIES/mobs_mc/textures/mobs_mc_villager_weaponsmith.png
Normal file
After Width: | Height: | Size: 967 B |
@ -10,14 +10,10 @@
|
|||||||
|
|
||||||
-- TODO: Particles
|
-- TODO: Particles
|
||||||
-- TODO: 4s Regeneration I after trade unlock
|
-- TODO: 4s Regeneration I after trade unlock
|
||||||
-- TODO: Breeding
|
|
||||||
-- TODO: Baby villagers
|
|
||||||
-- TODO: Spawning in villages
|
|
||||||
-- TODO: Behaviour:
|
-- TODO: Behaviour:
|
||||||
-- TODO: Walk around village, but do not leave it intentionally
|
|
||||||
-- TODO: Run into house on rain or danger, open doors
|
-- TODO: Run into house on rain or danger, open doors
|
||||||
-- TODO: Internal inventory, pick up items, trade with other villagers
|
-- TODO: Internal inventory, trade with other villagers
|
||||||
-- TODO: Farm stuff
|
-- TODO: Schedule stuff (work,sleep,father)
|
||||||
|
|
||||||
local S = minetest.get_translator("mobs_mc")
|
local S = minetest.get_translator("mobs_mc")
|
||||||
local N = function(s) return s end
|
local N = function(s) return s end
|
||||||
@ -61,15 +57,37 @@ if minetest.get_mapgen_setting("mg_name") == "v6" then
|
|||||||
TRADE_V6_BIRCH_SAPLING = { { "mcl_core:emerald", 8, 11 }, { "mcl_core:birchsapling", 1, 1 } }
|
TRADE_V6_BIRCH_SAPLING = { { "mcl_core:emerald", 8, 11 }, { "mcl_core:birchsapling", 1, 1 } }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local tiernames = {
|
||||||
|
"Novice",
|
||||||
|
"Apprentice",
|
||||||
|
"Journeyman",
|
||||||
|
"Expert",
|
||||||
|
"Master",
|
||||||
|
}
|
||||||
|
|
||||||
|
local badges = {
|
||||||
|
"default_wood.png",
|
||||||
|
"default_steel_block.png",
|
||||||
|
"default_gold_block.png",
|
||||||
|
"mcl_core_emerald_block.png",
|
||||||
|
"default_diamond_block.png",
|
||||||
|
}
|
||||||
|
|
||||||
local professions = {
|
local professions = {
|
||||||
unemployed = {
|
unemployed = {
|
||||||
name = N("Unemployed"),
|
name = N("Unemployed"),
|
||||||
texture = "mobs_mc_villager.png",
|
textures = {
|
||||||
|
"mobs_mc_villager.png",
|
||||||
|
"mobs_mc_villager.png",
|
||||||
|
},
|
||||||
trades = nil,
|
trades = nil,
|
||||||
},
|
},
|
||||||
farmer = {
|
farmer = {
|
||||||
name = N("Farmer"),
|
name = N("Farmer"),
|
||||||
texture = "mobs_mc_villager_farmer.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_farmer.png",
|
||||||
|
"mobs_mc_villager_farmer.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_composters:composter",
|
jobsite = "mcl_composters:composter",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -103,7 +121,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
fisherman = {
|
fisherman = {
|
||||||
name = N("Fisherman"),
|
name = N("Fisherman"),
|
||||||
texture = "mobs_mc_villager_farmer.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_fisherman.png",
|
||||||
|
"mobs_mc_villager_fisherman.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_barrels:barrel_closed",
|
jobsite = "mcl_barrels:barrel_closed",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -138,7 +159,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
fletcher = {
|
fletcher = {
|
||||||
name = N("Fletcher"),
|
name = N("Fletcher"),
|
||||||
texture = "mobs_mc_villager_farmer.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_fletcher.png",
|
||||||
|
"mobs_mc_villager_fletcher.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_fletching_table:fletching_table",
|
jobsite = "mcl_fletching_table:fletching_table",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -177,7 +201,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
shepherd ={
|
shepherd ={
|
||||||
name = N("Shepherd"),
|
name = N("Shepherd"),
|
||||||
texture = "mobs_mc_villager_farmer.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_sheperd.png",
|
||||||
|
"mobs_mc_villager_sheperd.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_loom:loom",
|
jobsite = "mcl_loom:loom",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -207,8 +234,11 @@ local professions = {
|
|||||||
},
|
},
|
||||||
librarian = {
|
librarian = {
|
||||||
name = N("Librarian"),
|
name = N("Librarian"),
|
||||||
texture = "mobs_mc_villager_librarian.png",
|
textures = {
|
||||||
jobsite = "mcl_villages:stonebrickcarved", --FIXME: lectern
|
"mobs_mc_villager_librarian.png",
|
||||||
|
"mobs_mc_villager_librarian.png",
|
||||||
|
},
|
||||||
|
jobsite = "mcl_books:bookshelf", --FIXME: lectern
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
{ { "mcl_core:paper", 24, 36 }, E1 },
|
{ { "mcl_core:paper", 24, 36 }, E1 },
|
||||||
@ -242,7 +272,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
cartographer = {
|
cartographer = {
|
||||||
name = N("Cartographer"),
|
name = N("Cartographer"),
|
||||||
texture = "mobs_mc_villager_librarian.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_cartographer.png",
|
||||||
|
"mobs_mc_villager_cartographer.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_cartography_table:cartography_table",
|
jobsite = "mcl_cartography_table:cartography_table",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -285,7 +318,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
armorer = {
|
armorer = {
|
||||||
name = N("Armorer"),
|
name = N("Armorer"),
|
||||||
texture = "mobs_mc_villager_smith.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_armorer.png",
|
||||||
|
"mobs_mc_villager_armorer.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_blast_furnace:blast_furnace",
|
jobsite = "mcl_blast_furnace:blast_furnace",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -298,7 +334,7 @@ local professions = {
|
|||||||
|
|
||||||
{
|
{
|
||||||
{ { "mcl_core:iron_ingot", 4, 4 }, E1 },
|
{ { "mcl_core:iron_ingot", 4, 4 }, E1 },
|
||||||
--{ { "mcl_core:emerald", 36, 36 }, { "FIXME: Bell", 1, 1 } },
|
{ { "mcl_core:emerald", 36, 36 }, { "mcl_bells:bell", 1, 1 } },
|
||||||
{ { "mcl_core:emerald", 3, 3 }, { "mcl_armor:leggings_chain", 1, 1 } },
|
{ { "mcl_core:emerald", 3, 3 }, { "mcl_armor:leggings_chain", 1, 1 } },
|
||||||
{ { "mcl_core:emerald", 1, 1 }, { "mcl_armor:boots_chain", 1, 1 } },
|
{ { "mcl_core:emerald", 1, 1 }, { "mcl_armor:boots_chain", 1, 1 } },
|
||||||
},
|
},
|
||||||
@ -322,7 +358,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
leatherworker = {
|
leatherworker = {
|
||||||
name = N("Leatherworker"),
|
name = N("Leatherworker"),
|
||||||
texture = "mobs_mc_villager_butcher.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_leatherworker.png",
|
||||||
|
"mobs_mc_villager_leatherworker.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_cauldrons:cauldron",
|
jobsite = "mcl_cauldrons:cauldron",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -351,7 +390,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
butcher = {
|
butcher = {
|
||||||
name = N("Butcher"),
|
name = N("Butcher"),
|
||||||
texture = "mobs_mc_villager_butcher.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_butcher.png",
|
||||||
|
"mobs_mc_villager_butcher.png",
|
||||||
|
},
|
||||||
jobsite = "mcl_smoker:smoker",
|
jobsite = "mcl_smoker:smoker",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
@ -381,8 +423,11 @@ local professions = {
|
|||||||
},
|
},
|
||||||
weapon_smith = {
|
weapon_smith = {
|
||||||
name = N("Weapon Smith"),
|
name = N("Weapon Smith"),
|
||||||
texture = "mobs_mc_villager_smith.png",
|
textures = {
|
||||||
jobsite = "mcl_villages:stonebrickcarved", --FIXME: grindstone
|
"mobs_mc_villager_weaponsmith.png",
|
||||||
|
"mobs_mc_villager_weaponsmith.png",
|
||||||
|
},
|
||||||
|
jobsite = "mcl_furnaces:furnace", --FIXME: grindstone
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
{ { "mcl_core:coal_lump", 15, 15 }, E1 },
|
{ { "mcl_core:coal_lump", 15, 15 }, E1 },
|
||||||
@ -392,7 +437,7 @@ local professions = {
|
|||||||
|
|
||||||
{
|
{
|
||||||
{ { "mcl_core:iron_ingot", 4, 4 }, E1 },
|
{ { "mcl_core:iron_ingot", 4, 4 }, E1 },
|
||||||
--{ { "mcl_core:emerald", 36, 36 }, { "FIXME: Bell", 1, 1 } },
|
{ { "mcl_core:emerald", 36, 36 }, { "mcl_bells:bell", 1, 1 } },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ { "mcl_core:flint", 7, 9 }, E1 },
|
{ { "mcl_core:flint", 7, 9 }, E1 },
|
||||||
@ -409,8 +454,11 @@ local professions = {
|
|||||||
},
|
},
|
||||||
tool_smith = {
|
tool_smith = {
|
||||||
name = N("Tool Smith"),
|
name = N("Tool Smith"),
|
||||||
texture = "mobs_mc_villager_smith.png",
|
textures = {
|
||||||
jobsite = "mcl_villages:stonebrickcarved", --FIXME: smithing table
|
"mobs_mc_villager_toolsmith.png",
|
||||||
|
"mobs_mc_villager_toolsmith.png",
|
||||||
|
},
|
||||||
|
jobsite = "mcl_anvils:anvil", --FIXME: smithing table
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
{ { "mcl_core:coal_lump", 15, 15 }, E1 },
|
{ { "mcl_core:coal_lump", 15, 15 }, E1 },
|
||||||
@ -422,7 +470,7 @@ local professions = {
|
|||||||
|
|
||||||
{
|
{
|
||||||
{ { "mcl_core:iron_ingot", 4, 4 }, E1 },
|
{ { "mcl_core:iron_ingot", 4, 4 }, E1 },
|
||||||
--{ { "mcl_core:emerald", 36, 36 }, { "FIXME: Bell", 1, 1 } },
|
{ { "mcl_core:emerald", 36, 36 }, { "mcl_bells:bell", 1, 1 } },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ { "mcl_core:flint", 30, 30 }, E1 },
|
{ { "mcl_core:flint", 30, 30 }, E1 },
|
||||||
@ -443,8 +491,11 @@ local professions = {
|
|||||||
},
|
},
|
||||||
cleric = {
|
cleric = {
|
||||||
name = N("Cleric"),
|
name = N("Cleric"),
|
||||||
texture = "mobs_mc_villager_priest.png",
|
textures = {
|
||||||
jobsite = "mcl_brewing:stand",
|
"mobs_mc_villager_priest.png",
|
||||||
|
"mobs_mc_villager_priest.png",
|
||||||
|
},
|
||||||
|
jobsite = "mcl_brewing:stand_000",
|
||||||
trades = {
|
trades = {
|
||||||
{
|
{
|
||||||
{ { "mcl_mobitems:rotten_flesh", 32, 32 }, E1 },
|
{ { "mcl_mobitems:rotten_flesh", 32, 32 }, E1 },
|
||||||
@ -472,7 +523,10 @@ local professions = {
|
|||||||
},
|
},
|
||||||
nitwit = {
|
nitwit = {
|
||||||
name = N("Nitwit"),
|
name = N("Nitwit"),
|
||||||
texture = "mobs_mc_villager.png",
|
textures = {
|
||||||
|
"mobs_mc_villager_nitwit.png",
|
||||||
|
"mobs_mc_villager_nitwit.png",
|
||||||
|
},
|
||||||
-- No trades for nitwit
|
-- No trades for nitwit
|
||||||
trades = nil,
|
trades = nil,
|
||||||
}
|
}
|
||||||
@ -483,48 +537,106 @@ for id, _ in pairs(professions) do
|
|||||||
table.insert(profession_names, id)
|
table.insert(profession_names, id)
|
||||||
end
|
end
|
||||||
|
|
||||||
local stand_still = function(self)
|
local jobsites={}
|
||||||
|
for _,n in pairs(profession_names) do
|
||||||
|
table.insert(jobsites,professions[n].jobsite)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function stand_still(self)
|
||||||
self.walk_chance = 0
|
self.walk_chance = 0
|
||||||
self.jump = false
|
self.jump = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function set_velocity(self, v)
|
local function init_trader_vars(self)
|
||||||
local yaw = (self.object:get_yaw() or 0) + self.rotate
|
if not self._max_trade_tier then
|
||||||
self.object:set_velocity({
|
self._max_trade_tier = 1
|
||||||
x = (math.sin(yaw) * -v),
|
end
|
||||||
y = self.object:get_velocity().y,
|
if not self._locked_trades then
|
||||||
z = (math.cos(yaw) * v),
|
self._locked_trades = 0
|
||||||
})
|
end
|
||||||
|
if not self._trading_players then
|
||||||
|
self._trading_players = {}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function go_to_pos(entity,b)
|
local function get_badge_textures(self)
|
||||||
local s=entity.object:get_pos()
|
local t = professions[self._profession].textures
|
||||||
local v = { x = b.x - s.x, z = b.z - s.z }
|
if self._profession == "unemployed" or self._profession == "nitwit" then return t end
|
||||||
local yaw = (math.atan(v.z / v.x) + math.pi / 2) - entity.rotate
|
local tier = self._max_trade_tier or 1
|
||||||
if b.x > s.x then yaw = yaw + math.pi end
|
return {
|
||||||
entity.object:set_yaw(yaw)
|
"[combine:64x64:0,0="..t[1]..":11,55=".. badges[tier].."\\^[resize\\:2x2",
|
||||||
set_velocity(entity,entity.follow_velocity)
|
t[2]
|
||||||
if vector.distance(b,s) < 5 then
|
}
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function set_textures(self)
|
||||||
|
self.object:set_properties({textures=get_badge_textures(self)})
|
||||||
end
|
end
|
||||||
|
|
||||||
local function go_home(entity)
|
local function go_home(entity)
|
||||||
entity.state = "go_home"
|
entity.state = "go_home"
|
||||||
local b=entity.bed
|
local b=entity._bed
|
||||||
if not b then return end
|
if not b then return end
|
||||||
if go_to_pos(entity,b) then
|
mobs:gopath(entity,b,function(entity,b)
|
||||||
|
if vector.distance(entity.object:get_pos(),b) < 2 then
|
||||||
entity.state = "stand"
|
entity.state = "stand"
|
||||||
set_velocity(entity,0)
|
set_velocity(entity,0)
|
||||||
entity.object:set_pos(b)
|
entity.object:set_pos(b)
|
||||||
local n=minetest.get_node(b)
|
local n=minetest.get_node(b)
|
||||||
if n and n.name ~= "mcl_beds:bed_red_bottom" then
|
if n and n.name ~= "mcl_beds:bed_red_bottom" then
|
||||||
entity.bed=nil --the stormtroopers have killed uncle owen
|
entity._bed=nil --the stormtroopers have killed uncle owen
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
----- JOBSITE LOGIC
|
||||||
|
local function get_profession_by_jobsite(js)
|
||||||
|
for k,v in pairs(professions) do
|
||||||
|
if v.jobsite == js then return k end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function employ(self,jobsite_pos)
|
||||||
|
local n = minetest.get_node(jobsite_pos)
|
||||||
|
local m = minetest.get_meta(jobsite_pos)
|
||||||
|
local p = get_profession_by_jobsite(n.name)
|
||||||
|
if p and m:get_string("villager") == "" then
|
||||||
|
self._profession=p
|
||||||
|
m:set_string("villager",self._id)
|
||||||
|
self._jobsite = jobsite_pos
|
||||||
|
set_textures(self)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function look_for_job(self)
|
||||||
|
local p = self.object:get_pos()
|
||||||
|
local nn = minetest.find_nodes_in_area(vector.offset(p,-48,-48,-48),vector.offset(p,48,48,48),jobsites)
|
||||||
|
for _,n in pairs(nn) do
|
||||||
|
local m=minetest.get_meta(n)
|
||||||
|
if m:get_string("villager") == "" then
|
||||||
|
--minetest.log("goingt to jobsite "..minetest.pos_to_string(n) )
|
||||||
|
local gp = mobs:gopath(self,n,function()
|
||||||
|
--minetest.log("arrived jobsite "..minetest.pos_to_string(n) )
|
||||||
|
end)
|
||||||
|
if gp then return end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local update_max_tradenum = function(self)
|
local function get_a_job(self)
|
||||||
|
local p = self.object:get_pos()
|
||||||
|
local nn = minetest.find_nodes_in_area(vector.offset(p,-8,-8,-8),vector.offset(p,8,8,8),jobsites)
|
||||||
|
for _,n in pairs(nn) do
|
||||||
|
if n and employ(self,n) then return true end
|
||||||
|
end
|
||||||
|
if self.state ~= "gowp" then look_for_job(self) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update_max_tradenum(self)
|
||||||
if not self._trades then
|
if not self._trades then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -539,31 +651,7 @@ local update_max_tradenum = function(self)
|
|||||||
self._max_tradenum = #trades
|
self._max_tradenum = #trades
|
||||||
end
|
end
|
||||||
|
|
||||||
local init_trader_vars = function(self)
|
local function init_trades(self, inv)
|
||||||
if not self._profession then
|
|
||||||
-- Select random profession from all professions with matching clothing
|
|
||||||
local texture = self.base_texture[1]
|
|
||||||
local matches = {}
|
|
||||||
for prof_id, prof in pairs(professions) do
|
|
||||||
if texture == prof.texture then
|
|
||||||
table.insert(matches, prof_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local p = math.random(1, #matches)
|
|
||||||
self._profession = matches[p]
|
|
||||||
end
|
|
||||||
if not self._max_trade_tier then
|
|
||||||
self._max_trade_tier = 1
|
|
||||||
end
|
|
||||||
if not self._locked_trades then
|
|
||||||
self._locked_trades = 0
|
|
||||||
end
|
|
||||||
if not self._trading_players then
|
|
||||||
self._trading_players = {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local init_trades = function(self, inv)
|
|
||||||
local profession = professions[self._profession]
|
local profession = professions[self._profession]
|
||||||
local trade_tiers = profession.trades
|
local trade_tiers = profession.trades
|
||||||
if trade_tiers == nil then
|
if trade_tiers == nil then
|
||||||
@ -614,7 +702,7 @@ local init_trades = function(self, inv)
|
|||||||
minetest.deserialize(self._trades)
|
minetest.deserialize(self._trades)
|
||||||
end
|
end
|
||||||
|
|
||||||
local set_trade = function(trader, player, inv, concrete_tradenum)
|
local function set_trade(trader, player, inv, concrete_tradenum)
|
||||||
local trades = minetest.deserialize(trader._trades)
|
local trades = minetest.deserialize(trader._trades)
|
||||||
if not trades then
|
if not trades then
|
||||||
init_trades(trader)
|
init_trades(trader)
|
||||||
@ -688,12 +776,17 @@ local function show_trade_formspec(playername, trader, tradenum)
|
|||||||
w2_formspec = "item_image[3,1;1,1;"..wanted2:to_string().."]"
|
w2_formspec = "item_image[3,1;1,1;"..wanted2:to_string().."]"
|
||||||
.."tooltip[3,1;0.8,0.8;"..F(wanted2:get_description()).."]"
|
.."tooltip[3,1;0.8,0.8;"..F(wanted2:get_description()).."]"
|
||||||
end
|
end
|
||||||
|
local tiername = tiernames[trader._max_trade_tier]
|
||||||
|
if tiername then
|
||||||
|
tiername = S(tiername)
|
||||||
|
else
|
||||||
|
tiername = S("Master")
|
||||||
|
end
|
||||||
local formspec =
|
local formspec =
|
||||||
"size[9,8.75]"
|
"size[9,8.75]"
|
||||||
.."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]"
|
.."background[-0.19,-0.25;9.41,9.49;mobs_mc_trading_formspec_bg.png]"
|
||||||
..disabled_img
|
..disabled_img
|
||||||
.."label[4,0;"..F(minetest.colorize("#313131", S(profession))).."]"
|
.."label[3,0;"..F(minetest.colorize("#313131", S(profession).." - "..tiername)) .."]"
|
||||||
.."list[current_player;main;0,4.5;9,3;9]"
|
.."list[current_player;main;0,4.5;9,3;9]"
|
||||||
.."list[current_player;main;0,7.74;9,1;]"
|
.."list[current_player;main;0,7.74;9,1;]"
|
||||||
..b_prev..b_next
|
..b_prev..b_next
|
||||||
@ -713,7 +806,7 @@ local function show_trade_formspec(playername, trader, tradenum)
|
|||||||
minetest.show_formspec(playername, tradeinv_name, formspec)
|
minetest.show_formspec(playername, tradeinv_name, formspec)
|
||||||
end
|
end
|
||||||
|
|
||||||
local update_offer = function(inv, player, sound)
|
local function update_offer(inv, player, sound)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local trader = player_trading_with[name]
|
local trader = player_trading_with[name]
|
||||||
local tradenum = player_tradenum[name]
|
local tradenum = player_tradenum[name]
|
||||||
@ -737,12 +830,12 @@ local update_offer = function(inv, player, sound)
|
|||||||
-- compass.
|
-- compass.
|
||||||
-- TODO: Remove these check functions when compass and clock are implemented
|
-- TODO: Remove these check functions when compass and clock are implemented
|
||||||
-- as single items.
|
-- as single items.
|
||||||
local check_special = function(special_item, group, wanted1, wanted2, input1, input2)
|
local function check_special(special_item, group, wanted1, wanted2, input1, input2)
|
||||||
if minetest.registered_aliases[special_item] then
|
if minetest.registered_aliases[special_item] then
|
||||||
special_item = minetest.registered_aliases[special_item]
|
special_item = minetest.registered_aliases[special_item]
|
||||||
end
|
end
|
||||||
if wanted1:get_name() == special_item then
|
if wanted1:get_name() == special_item then
|
||||||
local check_input = function(input, wanted, group)
|
local function check_input(input, wanted, group)
|
||||||
return minetest.get_item_group(input:get_name(), group) ~= 0 and input:get_count() >= wanted:get_count()
|
return minetest.get_item_group(input:get_name(), group) ~= 0 and input:get_count() >= wanted:get_count()
|
||||||
end
|
end
|
||||||
if check_input(input1, wanted1, group) then
|
if check_input(input1, wanted1, group) then
|
||||||
@ -757,7 +850,7 @@ local update_offer = function(inv, player, sound)
|
|||||||
end
|
end
|
||||||
-- Apply above function to all items which we consider special.
|
-- Apply above function to all items which we consider special.
|
||||||
-- This function succeeds if ANY item check succeeds.
|
-- This function succeeds if ANY item check succeeds.
|
||||||
local check_specials = function(wanted1, wanted2, input1, input2)
|
local function check_specials(wanted1, wanted2, input1, input2)
|
||||||
return check_special(COMPASS, "compass", wanted1, wanted2, input1, input2)
|
return check_special(COMPASS, "compass", wanted1, wanted2, input1, input2)
|
||||||
end
|
end
|
||||||
-- END OF SPECIAL HANDLING OF COMPASS
|
-- END OF SPECIAL HANDLING OF COMPASS
|
||||||
@ -811,7 +904,7 @@ local function return_item(itemstack, dropper, pos, inv_p)
|
|||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local return_fields = function(player)
|
local function return_fields(player)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local inv_t = minetest.get_inventory({type="detached", name = "mobs_mc:trade_"..name})
|
local inv_t = minetest.get_inventory({type="detached", name = "mobs_mc:trade_"..name})
|
||||||
local inv_p = player:get_inventory()
|
local inv_p = player:get_inventory()
|
||||||
@ -877,7 +970,7 @@ minetest.register_on_leaveplayer(function(player)
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
-- Return true if player is trading with villager, and the villager entity exists
|
-- Return true if player is trading with villager, and the villager entity exists
|
||||||
local trader_exists = function(playername)
|
local function trader_exists(playername)
|
||||||
local trader = player_trading_with[playername]
|
local trader = player_trading_with[playername]
|
||||||
return trader ~= nil and trader.object:get_luaentity() ~= nil
|
return trader ~= nil and trader.object:get_luaentity() ~= nil
|
||||||
end
|
end
|
||||||
@ -904,7 +997,7 @@ local trade_inventory = {
|
|||||||
wanted1:set_count(wanted1:get_count()*2)
|
wanted1:set_count(wanted1:get_count()*2)
|
||||||
wanted2:set_count(wanted2:get_count()*2)
|
wanted2:set_count(wanted2:get_count()*2)
|
||||||
-- BEGIN OF SPECIAL HANDLING FOR COMPASS
|
-- BEGIN OF SPECIAL HANDLING FOR COMPASS
|
||||||
local special_checks = function(wanted1, input1, input2)
|
local function special_checks(wanted1, input1, input2)
|
||||||
if wanted1:get_name() == COMPASS then
|
if wanted1:get_name() == COMPASS then
|
||||||
local compasses = 0
|
local compasses = 0
|
||||||
if (minetest.get_item_group(input1:get_name(), "compass") ~= 0) then
|
if (minetest.get_item_group(input1:get_name(), "compass") ~= 0) then
|
||||||
@ -1021,6 +1114,10 @@ local trade_inventory = {
|
|||||||
-- First-time trade unlock all trades and unlock next trade tier
|
-- First-time trade unlock all trades and unlock next trade tier
|
||||||
if trade.tier + 1 > trader._max_trade_tier then
|
if trade.tier + 1 > trader._max_trade_tier then
|
||||||
trader._max_trade_tier = trader._max_trade_tier + 1
|
trader._max_trade_tier = trader._max_trade_tier + 1
|
||||||
|
if trader._max_trade_tier > 5 then
|
||||||
|
trader._max_trade_tier = 5
|
||||||
|
end
|
||||||
|
set_textures(trader)
|
||||||
update_max_tradenum(trader)
|
update_max_tradenum(trader)
|
||||||
update_formspec = true
|
update_formspec = true
|
||||||
end
|
end
|
||||||
@ -1113,31 +1210,9 @@ mobs:register_mob("mobs_mc:villager", {
|
|||||||
visual = "mesh",
|
visual = "mesh",
|
||||||
mesh = "mobs_mc_villager.b3d",
|
mesh = "mobs_mc_villager.b3d",
|
||||||
textures = {
|
textures = {
|
||||||
{
|
|
||||||
"mobs_mc_villager.png",
|
"mobs_mc_villager.png",
|
||||||
"mobs_mc_villager.png", --hat
|
"mobs_mc_villager.png", --hat
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mobs_mc_villager_farmer.png",
|
|
||||||
"mobs_mc_villager_farmer.png", --hat
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mobs_mc_villager_priest.png",
|
|
||||||
"mobs_mc_villager_priest.png", --hat
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mobs_mc_villager_librarian.png",
|
|
||||||
"mobs_mc_villager_librarian.png", --hat
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mobs_mc_villager_butcher.png",
|
|
||||||
"mobs_mc_villager_butcher.png", --hat
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mobs_mc_villager_smith.png",
|
|
||||||
"mobs_mc_villager_smith.png", --hat
|
|
||||||
},
|
|
||||||
},
|
|
||||||
visual_size = {x=2.75, y=2.75},
|
visual_size = {x=2.75, y=2.75},
|
||||||
makes_footstep_sound = true,
|
makes_footstep_sound = true,
|
||||||
walk_velocity = 1.2,
|
walk_velocity = 1.2,
|
||||||
@ -1165,23 +1240,45 @@ mobs:register_mob("mobs_mc:villager", {
|
|||||||
die_loop = false,
|
die_loop = false,
|
||||||
},
|
},
|
||||||
follow = mobs_mc.follow.villager,
|
follow = mobs_mc.follow.villager,
|
||||||
|
nofollow = true,
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
fear_height = 4,
|
fear_height = 4,
|
||||||
jump = true,
|
jump = true,
|
||||||
walk_chance = DEFAULT_WALK_CHANCE,
|
walk_chance = DEFAULT_WALK_CHANCE,
|
||||||
on_rightclick = function(self, clicker)
|
_bed = nil,
|
||||||
if clicker:get_wielded_item():get_name() == "mcl_farming:bread" then
|
_id = nil,
|
||||||
if mobs:feed_tame(self, clicker, 1, true, true) then return end
|
_profession = "unemployed",
|
||||||
if mobs:protect(self, clicker) then return end
|
look_at_player = true,
|
||||||
|
pick_up = mobs_mc.follow.villager,
|
||||||
|
can_open_doors = true,
|
||||||
|
on_pick_up = function(self,itementity)
|
||||||
|
local clicker
|
||||||
|
for _,p in pairs(minetest.get_connected_players()) do
|
||||||
|
if vector.distance(p:get_pos(),self.object:get_pos()) < 10 then
|
||||||
|
clicker = p
|
||||||
end
|
end
|
||||||
if self.child then
|
end
|
||||||
|
if clicker then
|
||||||
|
mobs:feed_tame(self, clicker, 1, true, false)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return true --do not pick up
|
||||||
|
end,
|
||||||
|
on_rightclick = function(self, clicker)
|
||||||
|
local trg=vector.new(0,9,0)
|
||||||
|
if self._jobsite then
|
||||||
|
mobs:gopath(self,self._jobsite,function()
|
||||||
|
--minetest.log("arrived at jobsite")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
if self.child or self._profession == "unemployed" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Initiate trading
|
-- Initiate trading
|
||||||
|
init_trader_vars(self)
|
||||||
local name = clicker:get_player_name()
|
local name = clicker:get_player_name()
|
||||||
self._trading_players[name] = true
|
self._trading_players[name] = true
|
||||||
|
|
||||||
init_trader_vars(self)
|
|
||||||
if self._trades == nil then
|
if self._trades == nil then
|
||||||
init_trades(self)
|
init_trades(self)
|
||||||
end
|
end
|
||||||
@ -1219,10 +1316,6 @@ mobs:register_mob("mobs_mc:villager", {
|
|||||||
self._player_scan_timer = 0
|
self._player_scan_timer = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.bed and ( self.state == "go_home" or vector.distance(self.object:get_pos(),self.bed) > 50 ) then
|
|
||||||
go_home(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
self._player_scan_timer = self._player_scan_timer + dtime
|
self._player_scan_timer = self._player_scan_timer + dtime
|
||||||
-- Check infrequently to keep CPU load low
|
-- Check infrequently to keep CPU load low
|
||||||
if self._player_scan_timer > PLAYER_SCAN_INTERVAL then
|
if self._player_scan_timer > PLAYER_SCAN_INTERVAL then
|
||||||
@ -1244,15 +1337,31 @@ mobs:register_mob("mobs_mc:villager", {
|
|||||||
self.walk_chance = DEFAULT_WALK_CHANCE
|
self.walk_chance = DEFAULT_WALK_CHANCE
|
||||||
self.jump = true
|
self.jump = true
|
||||||
end
|
end
|
||||||
|
if self._bed and ( self.state ~= "go_home" and vector.distance(self.object:get_pos(),self._bed) > 50 ) then
|
||||||
|
go_home(self)
|
||||||
|
end
|
||||||
|
if self._profession == "unemployed" then
|
||||||
|
get_a_job(self)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
on_spawn = function(self)
|
on_spawn = function(self)
|
||||||
init_trader_vars(self)
|
if self._id then
|
||||||
|
set_textures(self)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
self._id=minetest.sha1(minetest.get_gametime()..minetest.pos_to_string(self.object:get_pos())..tostring(math.random()))
|
||||||
|
self._profession = "unemployed"
|
||||||
|
if math.random(100) == 1 then
|
||||||
|
self._profession = "nitwit"
|
||||||
|
end
|
||||||
|
set_textures(self)
|
||||||
end,
|
end,
|
||||||
on_die = function(self, pos)
|
on_die = function(self, pos)
|
||||||
-- Close open trade formspecs and give input back to players
|
-- Close open trade formspecs and give input back to players
|
||||||
local trading_players = self._trading_players
|
local trading_players = self._trading_players
|
||||||
|
if trading_players then
|
||||||
for name, _ in pairs(trading_players) do
|
for name, _ in pairs(trading_players) do
|
||||||
minetest.close_formspec(name, "mobs_mc:trade_"..name)
|
minetest.close_formspec(name, "mobs_mc:trade_"..name)
|
||||||
local player = minetest.get_player_by_name(name)
|
local player = minetest.get_player_by_name(name)
|
||||||
@ -1260,6 +1369,7 @@ mobs:register_mob("mobs_mc:villager", {
|
|||||||
return_fields(player)
|
return_fields(player)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -5,7 +5,13 @@ mcl_bells = {}
|
|||||||
local has_mcl_wip = minetest.get_modpath("mcl_wip")
|
local has_mcl_wip = minetest.get_modpath("mcl_wip")
|
||||||
|
|
||||||
function mcl_bells.ring_once(pos)
|
function mcl_bells.ring_once(pos)
|
||||||
minetest.sound_play( "mcl_bells_bell_stroke", { pos = pos, gain = 1.5, max_hear_distance = 300,});
|
minetest.sound_play( "mcl_bells_bell_stroke", { pos = pos, gain = 1.5, max_hear_distance = 150,})
|
||||||
|
local vv=minetest.get_objects_inside_radius(pos,150)
|
||||||
|
for _,o in pairs(vv) do
|
||||||
|
if o.type == "npc" then
|
||||||
|
mobs:gopath(o:get_luaentity(),pos,function() end)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node("mcl_bells:bell", {
|
minetest.register_node("mcl_bells:bell", {
|
||||||
|
@ -188,11 +188,41 @@ local function construct_node(p1, p2, name)
|
|||||||
end
|
end
|
||||||
minetest.log("warning", "[mcl_villages] Attempt to 'construct' inexistant nodes: " .. name)
|
minetest.log("warning", "[mcl_villages] Attempt to 'construct' inexistant nodes: " .. name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function spawn_iron_golem(pos)
|
||||||
|
local p = minetest.find_node_near(pos,50,"mcl_core:grass_path")
|
||||||
|
if p then
|
||||||
|
local l=minetest.add_entity(p,"mobs_mc:iron_golem"):get_luaentity()
|
||||||
|
if l then
|
||||||
|
l._home = p
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function spawn_villagers(minp,maxp)
|
||||||
|
local beds=minetest.find_nodes_in_area(vector.offset(minp,-20,-20,-20),vector.offset(maxp,20,20,20),{"mcl_beds:bed_red_bottom"})
|
||||||
|
for _,bed in pairs(beds) do
|
||||||
|
local m = minetest.get_meta(bed)
|
||||||
|
if m:get_string("villager") == "" then
|
||||||
|
local v=minetest.add_entity(bed,"mobs_mc:villager")
|
||||||
|
if v then
|
||||||
|
local l=v:get_luaentity()
|
||||||
|
l._bed = bed
|
||||||
|
m:set_string("villager",l._id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function init_nodes(p1, p2, size, rotation, pr)
|
local function init_nodes(p1, p2, size, rotation, pr)
|
||||||
construct_node(p1, p2, "mcl_itemframes:item_frame")
|
construct_node(p1, p2, "mcl_itemframes:item_frame")
|
||||||
construct_node(p1, p2, "mcl_furnaces:furnace")
|
construct_node(p1, p2, "mcl_furnaces:furnace")
|
||||||
construct_node(p1, p2, "mcl_anvils:anvil")
|
construct_node(p1, p2, "mcl_anvils:anvil")
|
||||||
|
|
||||||
|
construct_node(p1, p2, "mcl_smoker:smoker")
|
||||||
|
construct_node(p1, p2, "mcl_barrels:barrel_closed")
|
||||||
|
construct_node(p1, p2, "mcl_blast_furnace:blast_furnace")
|
||||||
|
construct_node(p1, p2, "mcl_brewing:stand_000")
|
||||||
local nodes = construct_node(p1, p2, "mcl_chests:chest")
|
local nodes = construct_node(p1, p2, "mcl_chests:chest")
|
||||||
if nodes and #nodes > 0 then
|
if nodes and #nodes > 0 then
|
||||||
for p=1, #nodes do
|
for p=1, #nodes do
|
||||||
@ -201,9 +231,30 @@ local function init_nodes(p1, p2, size, rotation, pr)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function settlements.place_schematics(settlement_info, pr)
|
function settlements.place_schematics(settlement_info, pr)
|
||||||
local building_all_info
|
local building_all_info
|
||||||
|
|
||||||
|
--attempt to place one belltower in the center of the village - this doesn't always work out great but it's a lot better than doing it first or last.
|
||||||
|
local belltower = table.remove(settlement_info,math.floor(#settlement_info/2))
|
||||||
|
if belltower then
|
||||||
|
mcl_structures.place_schematic(
|
||||||
|
vector.offset(belltower["pos"],0,0,0),
|
||||||
|
settlements.modpath.."/schematics/belltower.mts",
|
||||||
|
belltower["rotation"],
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
nil,
|
||||||
|
function(p1, p2, size, rotation, pr)
|
||||||
|
spawn_iron_golem(p1)
|
||||||
|
end,
|
||||||
|
pr
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
for i, built_house in ipairs(settlement_info) do
|
||||||
|
local is_last = i == #settlement_info
|
||||||
|
|
||||||
for j, schem in ipairs(settlements.schematic_table) do
|
for j, schem in ipairs(settlements.schematic_table) do
|
||||||
if settlement_info[i]["name"] == schem["name"] then
|
if settlement_info[i]["name"] == schem["name"] then
|
||||||
building_all_info = schem
|
building_all_info = schem
|
||||||
@ -271,7 +322,10 @@ function settlements.place_schematics(settlement_info, pr)
|
|||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
nil,
|
nil,
|
||||||
init_nodes,
|
function(p1, p2, size, rotation, pr)
|
||||||
|
init_nodes(p1, p2, size, rotation, pr)
|
||||||
|
spawn_villagers(p1,p2)
|
||||||
|
end,
|
||||||
pr
|
pr
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -21,7 +21,6 @@ minetest.register_node("mcl_villages:stonebrickcarved", {
|
|||||||
description = ("Chiseled Stone Village Bricks"),
|
description = ("Chiseled Stone Village Bricks"),
|
||||||
_doc_items_longdesc = doc.sub.items.temp.build,
|
_doc_items_longdesc = doc.sub.items.temp.build,
|
||||||
tiles = {"mcl_core_stonebrick_carved.png"},
|
tiles = {"mcl_core_stonebrick_carved.png"},
|
||||||
stack_max = 64,
|
|
||||||
drop = "mcl_core:stonebrickcarved",
|
drop = "mcl_core:stonebrickcarved",
|
||||||
groups = {pickaxey=1, stone=1, stonebrick=1, building_block=1, material_stone=1},
|
groups = {pickaxey=1, stone=1, stonebrick=1, building_block=1, material_stone=1},
|
||||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||||
@ -50,17 +49,6 @@ if minetest.get_modpath("mobs_mc") then
|
|||||||
end
|
end
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
local function spawn_villagers(minp,maxp)
|
|
||||||
local beds=minetest.find_nodes_in_area(minp,maxp,{"mcl_beds:bed_red_bottom"})
|
|
||||||
for _,bed in pairs(beds) do
|
|
||||||
minetest.get_meta(bed):set_string("villagebed","true")
|
|
||||||
local v=minetest.add_entity(bed,"mobs_mc:villager")
|
|
||||||
if v then
|
|
||||||
v:get_luaentity().bed = bed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- on map generation, try to build a settlement
|
-- on map generation, try to build a settlement
|
||||||
--
|
--
|
||||||
@ -79,10 +67,6 @@ local function build_a_settlement(minp, maxp, blockseed)
|
|||||||
|
|
||||||
-- evaluate settlement_info and place schematics
|
-- evaluate settlement_info and place schematics
|
||||||
settlements.place_schematics(settlement_info, pr)
|
settlements.place_schematics(settlement_info, pr)
|
||||||
|
|
||||||
minetest.after(60,function()
|
|
||||||
spawn_villagers(minp,maxp)
|
|
||||||
end) --give the village some time to fully generate
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ecb_village(blockpos, action, calls_remaining, param)
|
local function ecb_village(blockpos, action, calls_remaining, param)
|
||||||
|