1
0
Fork 0

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
mobs_head_rotation
cora 2022-05-22 13:22:41 +00:00
commit fc428da6fd
34 changed files with 903 additions and 592 deletions

View File

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

View File

@ -44,7 +44,7 @@ functions needed for the mob to work properly which contains the following:
'passive' when true allows animals to defend themselves when hit, 'passive' when true allows animals to defend themselves when hit,
otherwise they amble onwards. otherwise they amble onwards.
'walk_velocity' is the speed that your mob can walk around. 'walk_velocity' is the speed that your mob can walk around.
'run_velocity' is the speed your mob can run with, usually when attacking. 'run_velocity'is the speed your mob can run with, usually when attacking.
'walk_chance' has a 0-100 chance value your mob will walk from standing, 'walk_chance' has a 0-100 chance value your mob will walk from standing,
set to 0 for jumping mobs only. set to 0 for jumping mobs only.
'jump' when true allows your mob to jump updwards. 'jump' when true allows your mob to jump updwards.
@ -66,13 +66,13 @@ functions needed for the mob to work properly which contains the following:
walking, 0 to turn off height fear. walking, 0 to turn off height fear.
'fall_speed' has the maximum speed the mob can fall at, default is -10. 'fall_speed' has the maximum speed the mob can fall at, default is -10.
'fall_damage' when true causes falling to inflict damage. 'fall_damage' when true causes falling to inflict damage.
'water_damage' holds the damage per second infliced to mobs when standing in 'water_damage'holds the damage per second infliced to mobs when standing in
water (default: 0). water (default: 0).
'lava_damage' holds the damage per second inflicted to mobs when standing 'lava_damage' holds the damage per second inflicted to mobs when standing
in lava (default: 8). in lava (default: 8).
'fire_damage' holds the damage per second inflicted to mobs when standing 'fire_damage' holds the damage per second inflicted to mobs when standing
in fire (default: 1). in fire (default: 1).
'light_damage' holds the damage per second inflicted to mobs when it's too 'light_damage'holds the damage per second inflicted to mobs when it's too
bright (above 13 light). bright (above 13 light).
'suffocation' when true causes mobs to suffocate inside solid blocks (2 damage per second). 'suffocation' when true causes mobs to suffocate inside solid blocks (2 damage per second).
'floats' when set to 1 mob will float in water, 0 has them sink. 'floats' when set to 1 mob will float in water, 0 has them sink.
@ -119,7 +119,7 @@ functions needed for the mob to work properly which contains the following:
attacking. attacking.
'dogshoot_switch' allows switching between attack types by using timers 'dogshoot_switch' allows switching between attack types by using timers
(1 for shoot, 2 for dogfight) (1 for shoot, 2 for dogfight)
'dogshoot_count_max' contains how many seconds before switching from 'dogshoot_count_max'contains how many seconds before switching from
dogfight to shoot. dogfight to shoot.
'dogshoot_count2_max' contains how many seconds before switching from shoot 'dogshoot_count2_max' contains how many seconds before switching from shoot
to dogfight. to dogfight.
@ -136,7 +136,7 @@ functions needed for the mob to work properly which contains the following:
in minetest.conf is not false). in minetest.conf is not false).
'immune_to' is a table that holds specific damage when being hit by 'immune_to' is a table that holds specific damage when being hit by
certain items e.g. certain items e.g.
{"default:sword_wood", 0} -- causes no damage. {"default:sword_wood",0} -- causes no damage.
{"default:gold_lump", -10} -- heals by 10 health points. {"default:gold_lump", -10} -- heals by 10 health points.
{"default:coal_block", 20} -- 20 damage when hit on head with coal blocks. {"default:coal_block", 20} -- 20 damage when hit on head with coal blocks.
@ -194,9 +194,10 @@ 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.
'walk_start' when mob is walking around. 'walk_start' when mob is walking around.
'walk_end' 'walk_end'
'walk_speed' 'walk_speed'
@ -206,19 +207,20 @@ functions needed for the mob to work properly which contains the following:
'fly_start' when a mob is flying. 'fly_start' when a mob is flying.
'fly_end' 'fly_end'
'fly_speed' 'fly_speed'
'punch_start' when a mob melee attacks. 'punch_start'when a mob melee attacks.
'punch_end' 'punch_end'
'punch_speed' 'punch_speed'
'punch2_start' alternative melee attack animation. 'punch2_start' alternative melee attack animation.
'punch2_end' 'punch2_end'
'punch2_speed' 'punch2_speed'
'shoot_start' shooting animation. 'shoot_start'shooting animation.
'shoot_end' 'shoot_end'
'shoot_speed' 'shoot_speed'
'die_start' death animation 'die_start' death animation
'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
@ -297,7 +305,7 @@ enhance mob functionality and have them do many interesting things:
'on_die' a function that is called when the mob is killed; the 'on_die' a function that is called when the mob is killed; the
parameters are (self, pos). Return true to skip the builtin parameters are (self, pos). Return true to skip the builtin
death animation and death effects death animation and death effects
'on_rightclick' its same as in minetest.register_entity() 'on_rightclick'its same as in minetest.register_entity()
'on_blast' is called when an explosion happens near mob when using TNT 'on_blast' is called when an explosion happens near mob when using TNT
functions, parameters are (object, damage) and returns functions, parameters are (object, damage) and returns
(do_damage, do_knockback, drops) (do_damage, do_knockback, drops)
@ -308,13 +316,13 @@ enhance mob functionality and have them do many interesting things:
'on_breed' called when two similar mobs breed, paramaters are 'on_breed' called when two similar mobs breed, paramaters are
(parent1, parent2) objects, return false to stop child from (parent1, parent2) objects, return false to stop child from
being resized and owner/tamed flags and child textures being being resized and owner/tamed flags and child textures being
applied. Function itself must spawn new child mob. applied.Function itself must spawn new child mob.
'on_grown' is called when a child mob has grown up, only paramater is 'on_grown' is called when a child mob has grown up, only paramater is
(self). (self).
'do_punch' called when mob is punched with paramaters (self, hitter, 'do_punch' called when mob is punched with paramaters (self, hitter,
time_from_last_punch, tool_capabilities, direction), return time_from_last_punch, tool_capabilities, direction), return
false to stop punch damage and knockback from taking place. false to stop punch damage and knockback from taking place.
'custom_attack' when set this function is called instead of the normal mob 'custom_attack'when set this function is called instead of the normal mob
melee attack, parameters are (self, to_attack). melee attack, parameters are (self, to_attack).
'on_die' a function that is called when mob is killed (self, pos) 'on_die' a function that is called when mob is killed (self, pos)
'do_custom' a custom function that is called every tick while mob is 'do_custom' a custom function that is called every tick while mob is
@ -335,9 +343,9 @@ for each mob.
damage at all (cannot exceed self.breath_max). Breath damage at all (cannot exceed self.breath_max). Breath
decreases by 1 each second while in a node with drowning decreases by 1 each second while in a node with drowning
damage and increases by 1 each second otherwise. damage and increases by 1 each second otherwise.
'self.texture_list' contains list of all mob textures 'self.texture_list'contains list of all mob textures
'self.child_texture' contains mob child texture when growing up 'self.child_texture' contains mob child texture when growing up
'self.base_texture' contains current skin texture which was randomly 'self.base_texture'contains current skin texture which was randomly
selected from textures list selected from textures list
'self.gotten' this is used to track whether some special item has been 'self.gotten' this is used to track whether some special item has been
gotten from the mob, for example, wool from sheep. gotten from the mob, for example, wool from sheep.
@ -406,7 +414,7 @@ command which uses above names to make settings clearer:
For each mob that spawns with this function is a field in mobs.spawning_mobs. For each mob that spawns with this function is a field in mobs.spawning_mobs.
It tells if the mob should spawn or not. Default is true. So other mods can It tells if the mob should spawn or not.Default is true.So other mods can
only use the API of this mod by disabling the spawning of the default mobs in only use the API of this mod by disabling the spawning of the default mobs in
this mod. this mod.
@ -414,7 +422,7 @@ this mod.
mobs:spawn_abm_check(pos, node, name) mobs:spawn_abm_check(pos, node, name)
This global function can be changed to contain additional checks for mobs to This global function can be changed to contain additional checks for mobs to
spawn e.g. mobs that spawn only in specific areas and the like. By returning spawn e.g. mobs that spawn only in specific areas and the like.By returning
true the mob will not spawn. true the mob will not spawn.
'pos' holds the position of the spawning mob 'pos' holds the position of the spawning mob
@ -446,7 +454,7 @@ This function registers a arrow for mobs with the attack type shoot.
'name' is the name of the arrow 'name' is the name of the arrow
'definition' is a table with the following values: 'definition' is a table with the following values:
'visual' same is in minetest.register_entity() 'visual' same is in minetest.register_entity()
'visual_size' same is in minetest.register_entity() 'visual_size'same is in minetest.register_entity()
'textures' same is in minetest.register_entity() 'textures' same is in minetest.register_entity()
'velocity' the velocity of the arrow 'velocity' the velocity of the arrow
'drop' if set to true any arrows hitting a node will drop as item 'drop' if set to true any arrows hitting a node will drop as item
@ -482,7 +490,7 @@ This function registers a spawn egg which can be used by admin to properly spawn
'name' this is the name of your new mob to spawn e.g. "mob:sheep" 'name' this is the name of your new mob to spawn e.g. "mob:sheep"
'description' the name of the new egg you are creating e.g. "Spawn Sheep" 'description' the name of the new egg you are creating e.g. "Spawn Sheep"
'background' the texture displayed for the egg in inventory 'background'the texture displayed for the egg in inventory
'addegg' would you like an egg image in front of your texture (1 = yes, 'addegg' would you like an egg image in front of your texture (1 = yes,
0 = no) 0 = no)
'no_creative' when set to true this stops spawn egg appearing in creative 'no_creative' when set to true this stops spawn egg appearing in creative
@ -498,7 +506,7 @@ mobs:boom(self, pos, radius)
'radius' radius of explosion (typically set to 3) 'radius' radius of explosion (typically set to 3)
This function generates an explosion which removes nodes in a specific radius This function generates an explosion which removes nodes in a specific radius
and damages any entity caught inside the blast radius. Protection will limit and damages any entity caught inside the blast radius.Protection will limit
node destruction but not entity damage. node destruction but not entity damage.
@ -542,7 +550,7 @@ mobs:protect(self, clicker)
This function can be used to right-click any tamed mob with mobs:protector item, This function can be used to right-click any tamed mob with mobs:protector item,
this will protect the mob from harm inside of a protected area from other this will protect the mob from harm inside of a protected area from other
players. Will return true when mob right-clicked with mobs:protector item. players.Will return true when mob right-clicked with mobs:protector item.
'self' mob information 'self' mob information
'clicker' player information 'clicker' player information
@ -578,7 +586,7 @@ This function allows an attached player to move the mob around and animate it at
same time. same time.
'self' mob information 'self' mob information
'move_animation' string containing movement animation e.g. "walk" 'move_animation'string containing movement animation e.g. "walk"
'stand_animation' string containing standing animation e.g. "stand" 'stand_animation' string containing standing animation e.g. "stand"
'can_fly' if true then jump and sneak controls will allow mob to fly 'can_fly' if true then jump and sneak controls will allow mob to fly
up and down up and down
@ -596,7 +604,7 @@ controls.
'can_shoot' true if mob can fire arrow (sneak and left mouse button 'can_shoot' true if mob can fire arrow (sneak and left mouse button
fires) fires)
'arrow_entity' name of arrow entity used for firing 'arrow_entity' name of arrow entity used for firing
'move_animation' string containing name of pre-defined animation e.g. "walk" 'move_animation'string containing name of pre-defined animation e.g. "walk"
or "fly" etc. or "fly" etc.
'stand_animation' string containing name of pre-defined animation e.g. 'stand_animation' string containing name of pre-defined animation e.g.
"stand" or "blink" etc. "stand" or "blink" etc.
@ -623,7 +631,7 @@ Certain variables need to be set before using the above functions:
'self.accel' acceleration speed 'self.accel' acceleration speed
'self.terrain_type' integer containing terrain mob can walk on 'self.terrain_type' integer containing terrain mob can walk on
(1 = water, 2 or 3 = land) (1 = water, 2 or 3 = land)
'self.driver_attach_at' position offset for attaching player to mob 'self.driver_attach_at'position offset for attaching player to mob
'self.driver_eye_offset' position offset for attached player view 'self.driver_eye_offset' position offset for attached player view
'self.driver_scale' sets driver scale for mobs larger than {x=1, y=1} 'self.driver_scale' sets driver scale for mobs larger than {x=1, y=1}
@ -642,7 +650,7 @@ External Settings for "minetest.conf"
multiplied by this number), defaults to 1.0. multiplied by this number), defaults to 1.0.
'mob_spawn_chance' multiplies chance of all mobs spawning and can be set 'mob_spawn_chance' multiplies chance of all mobs spawning and can be set
to 0.5 to have mobs spawn more or 2.0 to spawn less. to 0.5 to have mobs spawn more or 2.0 to spawn less.
e.g. 1 in 7000 * 0.5 = 1 in 3500 so better odds of e.g.1 in 7000 * 0.5 = 1 in 3500 so better odds of
spawning. spawning.
'mobs_spawn' if false then mobs no longer spawn without spawner or 'mobs_spawn' if false then mobs no longer spawn without spawner or
spawn egg. spawn egg.

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 866 B

After

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 848 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 896 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 768 B

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 866 B

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

View File

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

View File

@ -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", {

View File

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

View File

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

Binary file not shown.