Version 1.1

Added sheeps, fixed issues, restructured code
master
BlockMen 2014-03-13 11:19:32 +01:00
parent d5db6af4de
commit 70e43325ed
20 changed files with 7511 additions and 299 deletions

View File

@ -2,11 +2,11 @@ Minetest mod "Creatures"
=======================
by BlockMen (c) 2014
Version: 1.0.1 Beta
Version: 1.1 Beta
About
~~~~~
This mod add (currently only) hostile mobs to Minetest, so far Zombies and Ghosts.
This mod adds 2 hostile and 1 friendly mob to Minetest, so far zombies, ghosts and sheeps.
Zombies can spawn to every day-time in the world as long there is not to much light.
So you will find some in caves, dark forests and ofc a lot at night. If they notice you they will attack.
@ -14,14 +14,23 @@ Zombies have 20 HP (like players) and drop rotten flesh randomly.
Ghosts only spawn at night-time. Also they don't spawn underground and are a bit more rare than zombies.
They are flying in the world and attack you aswell if they notice you.
Ghosts have 15 HP and don't drop any items atm (might be changed if i have an idea what they could drop).
Ghosts have 12 HP and don't drop any items atm (might be changed if i have an idea what they could drop).
Sheeps spawn only at day-time and are friendly mobs. They remain around 5 minutes in the world unless there
are other sheeps around, then there is no fixed limit. If there is grass (dirt with grass) they eat the grass
and get new wool that way.
Sheeps have 8 HP and drop 1-2 wool when punched. They need to eat grass until they can produce new wool.
They can't harm you in your house (in case there is no door open). If it becomes day both mobs will take damage
by the sunlight, so they will die after a while.
Notice: You weapons get damage when hitting a zombie or ghost.
Notice: Weapons and tools get damaged when hitting a zombie or ghost. The wearout is calculated on the damage amout
of the tools/weapons. The more damage they can do that longer they can be used.
Example:
- Diamond Sword: 1500 uses
- Wooden Sword: 30 uses
@ -39,6 +48,13 @@ following sounds are created by Under7dude (freesound.org)
- creatures_zombie.3.ogg, CC0
- creatures_zombie_death.ogg, CC0
following sounds are created by confusion_music (freesound.org)
- creatures_sheep.1.ogg, CC-BY 3.0
- creatures_sheep.2.ogg, CC-BY 3.0
following sound is created by Yuval (freesound.org)
- creatures_sheep.3.ogg, CC-BY 3.0
All other sounds (c) Copyright BlockMen (2014), CC-BY 3.0
Changelog:
@ -46,6 +62,15 @@ Changelog:
# 1.0.1
- fixed incompatibility with pyramids mod
# 1.1
- new mob: sheep
- fixed crash caused by unknown node
- fixed spawning, added spawn limit
- fixed weapon & tool damage
- tweaked and restructured code
- ghosts only spawn on grass and desert-sand blocks
- ghosts have now 12 HP (instead 15 HP)
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want

View File

@ -1 +1,2 @@
default
default
wool

104
ghost.lua
View File

@ -2,17 +2,17 @@ local g_chillaxin_speed = 2
local g_animation_speed = 10
local g_mesh = "creatures_mob.x"
local g_texture = {"creatures_ghost.png"}
local g_hp = 15
local g_hp = 12
local g_drop = ""
local g_player_radius = 14
local g_hit_radius = 1
local g_ll = 7
creatures.g_ll = 7
local g_sound_normal = "creatures_ghost"
local g_sound_hit = "creatures_ghost_hit"
local g_sound_dead = "creatures_ghost_death"
local g_spawn_nodes = {"default:dirt_with_grass","default:stone","default:dirt","default:desert_sand"}
creatures.g_spawn_nodes = {"default:dirt_with_grass","default:desert_sand"}
local function g_get_animations()
return {
@ -21,13 +21,6 @@ local function g_get_animations()
}
end
local ANIM_STAND = 1
local ANIM_SIT = 2
local ANIM_LAY = 3
local ANIM_WALK = 4
local ANIM_WALK_MINE = 5
local ANIM_MINE = 6
function g_hit(self)
local sound = g_sound_hit
if self.object:get_hp() < 1 then sound = g_sound_dead end
@ -85,7 +78,7 @@ GHOST_DEF.on_activate = function(self)
self.anim = g_get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, g_animation_speed, 0)
self.npc_anim = ANIM_STAND
self.object:setacceleration({x=0,y=0,z=0})--20
self.object:setacceleration({x=0,y=0,z=0})
self.state = 1
self.object:set_hp(g_hp)
self.object:set_armor_groups({fleshy=130})
@ -113,19 +106,8 @@ GHOST_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabili
elseif self.state >= 2 then
self.state = 9
end
--add wear to swords
if not minetest.setting_getbool("creative_mode") then
local item = puncher:get_wielded_item()
local def = item:get_definition()
if def and def.tool_capabilities and def.tool_capabilities.groupcaps
and def.tool_capabilities.groupcaps.snappy then
local uses = def.tool_capabilities.groupcaps.snappy.uses or 10
uses = uses*2 --since default values are too low
local wear = 65535/uses
item:add_wear(wear)
puncher:set_wielded_item(item)
end
end
-- add wear to sword/tool
creatures.add_wear(puncher, tool_capabilities)
end
end
@ -151,7 +133,6 @@ GHOST_DEF.on_step = function(self, dtime)
-- death
if self.object:get_hp() < 1 then
--self.object:setvelocity({x=0,y=-20,z=0})
self.object:set_hp(0)
self.attacker = ""
self.state = 0
@ -167,10 +148,12 @@ GHOST_DEF.on_step = function(self, dtime)
-- die when in water, lava or sunlight
local wtime = minetest.env:get_timeofday()
local ll = minetest.env:get_node_light({x=current_pos.x,y=current_pos.y+1,z=current_pos.z}) or 0
if current_node.name == "default:water_source" or
current_node.name == "default:water_flowing" or
current_node.name == "default:lava_source" or
current_node.name == "default:lava_flowing" or
local nn = nil
if current_node ~= nil then nn = current_node.name end
if nn ~= nil and nn == "default:water_source" or
nn == "default:water_flowing" or
nn == "default:lava_source" or
nn == "default:lava_flowing" or
(wtime > 0.2 and wtime < 0.805 and current_pos.y > 0 and ll > 11) then
self.sound_timer = self.sound_timer + dtime
if self.sound_timer >= 0.8 then
@ -241,10 +224,10 @@ GHOST_DEF.on_step = function(self, dtime)
self.direction = {x = math.sin(self.yaw)*-1, y = 0, z = math.cos(self.yaw)}
end
self.object:setvelocity({x=0,y=self.object:getvelocity().y,z=0})
if self.npc_anim ~= ANIM_STAND then
if self.npc_anim ~= creatures.ANIM_STAND then
self.anim = g_get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, g_animation_speed, 0)
self.npc_anim = ANIM_STAND
self.npc_anim = creatures.ANIM_STAND
end
if self.attacker ~= "" then
self.direction = {x = math.sin(self.yaw)*-1, y = 0, z = math.cos(self.yaw)}
@ -264,10 +247,10 @@ GHOST_DEF.on_step = function(self, dtime)
self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = 0, z = math.cos(self.yaw)}
end
if self.npc_anim ~= ANIM_WALK then
if self.npc_anim ~= creatures.ANIM_WALK then
self.anim = g_get_animations()
self.object:set_animation({x=self.anim.walk_START,y=self.anim.walk_END}, g_animation_speed, 0)
self.npc_anim = ANIM_WALK
self.npc_anim = creatures.ANIM_WALK
end
--jump
if self.direction ~= nil and self.attacker ~= "" then
@ -311,58 +294,3 @@ GHOST_DEF.on_step = function(self, dtime)
end
minetest.register_entity("creatures:ghost", GHOST_DEF)
--spawn-egg
minetest.register_craftitem("creatures:ghost_spawn_egg", {
description = "Ghost spawn-egg",
inventory_image = "creatures_egg_ghost.png",
liquids_pointable = false,
stack_max = 99,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local p = pointed_thing.above
p.y = p.y+0.5
creatures.spawn(p, 1, "creatures:ghost")
if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end
return itemstack
end
end,
})
if not minetest.setting_getbool("only_peaceful_mobs") then
-- spawn randomly in world
minetest.register_abm({
nodenames = g_spawn_nodes,
interval = 44.0,
chance = 7500,
action = function(pos, node, active_object_count, active_object_count_wider)
if pos.y < 0 then return end
pos.y = pos.y+1
local ll = minetest.env:get_node_light(pos)
local wtime = minetest.env:get_timeofday()
if not ll then
return
end
if ll >= g_ll then
return
end
if ll < -1 then
return
end
if minetest.env:get_node(pos).name ~= "air" then
return
end
pos.y = pos.y+1
if minetest.env:get_node(pos).name ~= "air" then
return
end
if (wtime > 0.2 and wtime < 0.805) then
return
end
creatures.spawn(pos, 1, "creatures:ghost")
end
})
end

View File

@ -1,12 +1,100 @@
creatures = {}
function creatures.spawn(pos, number, mob)
print("spawn"..mob)
--log spawning?
creatures.ANIM_STAND = 1
creatures.ANIM_SIT = 2
creatures.ANIM_LAY = 3
creatures.ANIM_WALK = 4
creatures.ANIM_EAT = 5
creatures.ANIM_RUN = 6
local tool_uses = {0, 30, 110, 150, 280, 300, 500, 1000}
-- helping functions
function creatures.spawn(pos, number, mob, limit, range)
if not pos or not number or not mob then return end
if number < 1 then return end
if limit == nil then limit = 1 end
if range == nil then range = 10 end
local m_name = string.sub(mob,11)
local res,mobs,player_near = creatures.find_mates(pos, m_name, range)
for i=1,number do
minetest.env:add_entity(pos, mob)
local x = 1/math.random(1,3)
local z = 1/math.random(1,3)
local p = {x=pos.x+x,y=pos.y,z=pos.z+z}
if mobs+i <= limit then
minetest.after(i/5,function()
minetest.env:add_entity(p, mob)
minetest.log("action", "Spawned "..mob.." at ("..pos.x..","..pos.y..","..pos.z..")")
end)
end
end
end
function creatures.add_wear(player, def)
if not minetest.setting_getbool("creative_mode") then
local item = player:get_wielded_item()
if def and def.damage_groups and def.damage_groups.fleshy then
local uses = tool_uses[def.damage_groups.fleshy] or 0
if uses > 0 then
local wear = 65535/uses
item:add_wear(wear)
player:set_wielded_item(item)
end
end
end
end
function creatures.drop(pos, items, dir)
if dir == nil then
dir = {x=1,y=1,z=1}
end
for _,item in ipairs(items) do
for i=1,item.count do
local x = 1/math.random(1,5)*dir.x--math.random(0, 6)/3 - 0.5*dir.x
local z = 1/math.random(1,5)*dir.z--math.random(0, 6)/3 - 0.5*dir.z
local p = {x=pos.x+x,y=pos.y,z=pos.z+z}
local node = minetest.get_node_or_nil(p)
if node == nil or not node.name or node.name ~= "air" then
p = pos
end
local obj = minetest.env:add_item(p, {name=item.name})
end
end
end
function creatures.find_mates(pos, name, radius)
local player_near = false
local mobs = 0
for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, radius)) do
if obj:is_player() then
player_near = true
else
if obj:get_luaentity().mob_name == name then mobs = mobs + 1 end
end
end
if mobs > 1 then
return true,mobs,player_near
end
return false,mobs,player_near
end
function creatures.compare_pos(pos1,pos2)
if pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z then
return true
end
return false
end
-- hostile mobs
dofile(minetest.get_modpath("creatures").."/ghost.lua")
dofile(minetest.get_modpath("creatures").."/zombie.lua")
dofile(minetest.get_modpath("creatures").."/zombie.lua")
-- friendly mobs
dofile(minetest.get_modpath("creatures").."/sheep.lua")
-- spawning
dofile(minetest.get_modpath("creatures").."/spawn.lua")
dofile(minetest.get_modpath("creatures").."/spawners.lua")
-- other stuff
dofile(minetest.get_modpath("creatures").."/items.lua")

64
items.lua Normal file
View File

@ -0,0 +1,64 @@
-- drop items
minetest.register_craftitem("creatures:flesh", {
description = "Flesh",
inventory_image = "creatures_rotten_flesh.png",
on_use = minetest.item_eat(4),
})
minetest.register_craftitem("creatures:rotten_flesh", {
description = "Rotten Flesh",
inventory_image = "creatures_rotten_flesh.png",
on_use = minetest.item_eat(1),
})
-- spawn-eggs
minetest.register_craftitem("creatures:zombie_spawn_egg", {
description = "Zombie spawn-egg",
inventory_image = "creatures_egg_zombie.png",
liquids_pointable = false,
stack_max = 99,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local p = pointed_thing.above
p.y = p.y+1
creatures.spawn(p, 1, "creatures:zombie", 1, 1)
if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end
return itemstack
end
end,
})
minetest.register_craftitem("creatures:ghost_spawn_egg", {
description = "Ghost spawn-egg",
inventory_image = "creatures_egg_ghost.png",
liquids_pointable = false,
stack_max = 99,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local p = pointed_thing.above
p.y = p.y+0.5
creatures.spawn(p, 1, "creatures:ghost", 1, 1)
if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end
return itemstack
end
end,
})
minetest.register_craftitem("creatures:sheep_spawn_egg", {
description = "Sheep spawn-egg",
inventory_image = "creatures_egg_sheep.png",
liquids_pointable = false,
stack_max = 99,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local p = pointed_thing.above
p.y = p.y+0.5
creatures.spawn(p, 1, "creatures:sheep", 1, 1)
if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end
return itemstack
end
end,
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

After

Width:  |  Height:  |  Size: 511 B

BIN
models/creatures_sheep.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

6751
models/creatures_sheep.x Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

After

Width:  |  Height:  |  Size: 264 B

345
sheep.lua Normal file
View File

@ -0,0 +1,345 @@
local s_chillaxin_speed = 1.5
local s_animation_speed = 15
local s_mesh = "creatures_sheep.x"
local s_texture = {"creatures_sheep.png"}
local s_hp = 8
local s_life_max = 80 --~5min
local s_drop = "wool:white"
local s_player_radius = 14
local s_sound_normal = "creatures_sheep"
local s_sound_hit = "creatures_sheep"
local s_sound_dead = "creatures_sheep"
creatures.s_spawn_nodes = {"default:dirt_with_grass"}
local function s_get_animations()
return {
stand_START = 0,
stand_END = 80,
walk_START = 81,
walk_END = 100,
eat_START = 107,
eat_END = 185
}
end
local function s_eat_anim(self)
self.object:set_animation({x=self.anim.eat_START,y=self.anim.eat_END}, s_animation_speed, 0)
self.npc_anim = creatures.ANIM_EAT
end
function s_hit(self)
local sound = s_sound_hit
if self.object:get_hp() < 1 then sound = s_sound_dead end
minetest.sound_play(sound, {pos = self.object:getpos(), max_hear_distance = 10, loop = false, gain = 0.4})
prop = {
mesh = s_mesh,
textures = {self.txture[1].."^creatures_sheep_hit.png"},
}
self.object:set_properties(prop)
self.can_punch = false
minetest.after(0.4, function()
s_update_visuals_def(self)
end)
end
function s_update_visuals_def(self)
self.txture = {"creatures_sheep.png"}
if not self.has_wool then
self.txture = {"creatures_sheep_shaved.png"}
end
prop = {
mesh = s_mesh,
textures = self.txture,
}
self.object:set_properties(prop)
end
SHEEP_DEF = {
physical = true,
collisionbox = {-0.4, -0.01, -0.6, 0.4, 0.9, 0.4},
visual = "mesh",
visual_size = {x=1, y=1},
mesh = s_mesh,
textures = s_texture,
txture = s_texture,
makes_footstep_sound = true,
npc_anim = 0,
lifetime = 0,
timer = 0,
turn_timer = 0,
vec = 0,
yaw = 0,
yawwer = 0,
has_wool = true,
state = 1,
can_punch = true,
dead = false,
jump_timer = 0,
last_pos = {x=0,y=0,z=0},
punch_timer = 0,
sound_timer = 0,
mob_name = "sheep"
}
SHEEP_DEF.get_staticdata = function(self)
return minetest.serialize({
itemstring = self.itemstring,
timer = self.timer,
txture = self.txture,
has_wool = self.has_wool,
lifetime = self.lifetime,
})
end
SHEEP_DEF.on_activate = function(self, staticdata, dtime_s)
self.txture = s_texture
s_update_visuals_def(self)
self.anim = s_get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, s_animation_speed, 0)
self.npc_anim = ANIM_STAND
self.object:setacceleration({x=0,y=-20,z=0})
self.object:setyaw(self.object:getyaw()+((math.random(0,90)-45)/45*math.pi))
self.lastpos = self.object:getpos()
self.state = 1
self.object:set_hp(s_hp)
self.object:set_armor_groups({fleshy=130})
self.can_punch = true
self.dead = false
self.has_wool = true
self.lifetime = 0
if staticdata then
local tmp = minetest.deserialize(staticdata)
if tmp and tmp.timer then
self.timer = tmp.timer
end
if tmp and tmp.has_wool ~= nil then
self.has_wool = tmp.has_wool
end
if tmp and tmp.lifetime ~= nil then
self.lifetime = tmp.lifetime
end
if not self.has_wool then
s_update_visuals_def(self)
end
end
end
SHEEP_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if not self.can_punch then return end
--SET RUN state (panic)
self.state = 4
self.timer = 0
if puncher ~= nil then
if time_from_last_punch >= 0.2 then --0.45
s_hit(self)
local v = self.object:getvelocity()
self.direction = {x=v.x, y=v.y, z=v.z}
self.punch_timer = 0
self.object:setvelocity({x=dir.x*2.5,y=5.2,z=dir.z*2.5})
self.state = 9
-- add wear to sword/tool
creatures.add_wear(puncher, tool_capabilities)
end
local my_pos = self.object:getpos()
my_pos.y = my_pos.y + 0.5
-- drop 1-2 whool when punched
if self.has_wool then
self.has_wool = false
creatures.drop(my_pos, {{name=s_drop, count=math.random(1,2)}}, dir)
end
end
end
SHEEP_DEF.on_step = function(self, dtime)
if self.dead then return end
self.timer = self.timer + 0.01
self.lifetime = self.lifetime + 0.01
self.turn_timer = self.turn_timer + 0.01
self.jump_timer = self.jump_timer + 0.01
self.punch_timer = self.punch_timer + 0.01
self.sound_timer = self.sound_timer + 0.01
local current_pos = self.object:getpos()
local current_node = minetest.env:get_node(current_pos)
-- death
if self.object:get_hp() < 1 then
self.object:setvelocity({x=0,y=-20,z=0})
self.object:set_hp(0)
self.state = 0
self.dead = true
minetest.sound_play(s_sound_dead, {pos = current_pos, max_hear_distance = 10, gain = 0.9})
self.object:set_animation({x=self.anim.lay_START,y=self.anim.lay_END}, s_animation_speed, 0)
minetest.after(1, function()
if self.has_wool then
local obj = minetest.env:add_item(current_pos, s_drop)
end
self.object:remove()
end)
end
-- die if old and alone
if self.lifetime > s_life_max then
if creatures.find_mates(current_pos, "sheep", 18) then
self.lifetime = 0
else
self.object:set_hp(0)
self.state = 0
self.dead = true
self.object:remove()
return
end
end
-- die when in water, lava
local wtime = minetest.env:get_timeofday()
local ll = minetest.env:get_node_light({x=current_pos.x,y=current_pos.y+1,z=current_pos.z}) or 0
local nn = nil
if current_node ~= nil then nn = current_node.name end
if nn ~= nil and nn == "default:water_source" or
nn == "default:water_flowing" or
nn == "default:lava_source" or
nn == "default:lava_flowing" then
self.sound_timer = self.sound_timer + 0.1
if self.sound_timer >= 0.8 then
local damage = 2
self.sound_timer = 0
self.object:set_hp(self.object:get_hp()-damage)
s_hit(self)
end
end
-- update moving state depending on current state
if self.state < 4 then
if self.timer > 4/self.state then
self.timer = 0
local new = math.random(1,3)
if self.state == 3 then new = 1 end
self.state = new
s_update_visuals_def(self)
end
elseif self.state == 4 and self.timer > 1.5 then
self.state = 2
self.timer = 0
end
-- play random sound
if self.sound_timer > self.timer + math.random(5,self.lifetime/2) then
minetest.sound_play(s_sound_normal, {pos = current_pos, max_hear_distance = 10, gain = 0.7})
self.sound_timer = 0
end
-- after knocked back
if self.state >= 8 then
if self.punch_timer > 0.15 then
if self.state == 9 then
self.object:setvelocity({x=self.direction.x*s_chillaxin_speed,y=-20,z=self.direction.z*s_chillaxin_speed})
self.state = 4
self.punch_timer = 0
elseif self.state == 8 then
self.object:setvelocity({x=0,y=-20,z=0})
self.state = 1
end
self.can_punch = true
end
end
--STANDING
if self.state == 1 then
self.yawwer = true
if self.turn_timer > math.random(1,4) then
local last = self.yaw
self.yaw = last + math.random(-0.5,1)
if self.yaw > 22 or self.yaw < -17 then self.yaw = 0 end
self.object:setyaw(self.yaw)
self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end
self.object:setvelocity({x=0,y=self.object:getvelocity().y,z=0})
if self.npc_anim ~= creatures.ANIM_STAND then
self.anim = s_get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, s_animation_speed, 0)
self.npc_anim = creatures.ANIM_STAND
end
end
-- stop walking when not moving
if self.state == 2 and creatures.compare_pos(self.object:getpos(),self.lastpos) and self.jump_timer <= 0.2 then
self.state = 1
end
-- WALKING
if self.state == 2 or self.state == 4 then
self.lastpos = self.object:getpos()
local speed = 1
local anim = creatures.ANIM_WALK
if self.state == 4 then
speed = 2.2
anim = creatures.ANIM_RUN
end
--[[if self.farmer ~= "" then
--use this for following weed, etc
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end]]
if self.direction ~= nil then
self.object:setvelocity({x=self.direction.x*s_chillaxin_speed*speed,y=self.object:getvelocity().y,z=self.direction.z*s_chillaxin_speed*speed})
end
if (self.turn_timer > math.random(0.8,2)) or (self.state == 4 and self.turn_timer > 0.2) then
if self.state == 2 then
local last = self.yaw
self.yaw = last + math.random(-1,0.5)
if self.yaw > 22 or self.yaw < -17 then self.yaw = 0 end
else
self.yaw = 360 * math.random()
end
self.object:setyaw(self.yaw)
self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end
if self.npc_anim ~= anim then
self.object:set_animation({x=self.anim.walk_START,y=self.anim.walk_END}, s_animation_speed*speed, 0)
self.npc_anim = anim
end
--jump
if self.direction ~= nil then
if self.jump_timer > 0.2 then
self.jump_timer = 0
local p = current_pos
local n = minetest.env:get_node({x=p.x + self.direction.x,y=p.y,z=p.z + self.direction.z})
if n and n.name and minetest.registered_items[n.name].walkable and minetest.registered_items[n.name].groups.fences == nil and n.name ~= "default:fence_wood" then
self.object:setvelocity({x=self.object:getvelocity().x,y=6.85,z=self.object:getvelocity().z})
end
end
end
end
-- EATING
if self.state == 3 then--and not self.has_wool then
self.object:setvelocity({x=0,y=self.object:getvelocity().y,z=0})
local p = {x=current_pos.x,y=current_pos.y-1,z=current_pos.z}
local n = minetest.get_node(p) or nil
if n and n.name and n.name == "default:dirt_with_grass" then
if self.timer == 0 then
s_eat_anim(self)
self.timer = 0.45
end
minetest.after(1.8,function()
minetest.set_node(p,{name="default:dirt"})
self.has_wool = true
end)
end
end
end
minetest.register_entity("creatures:sheep", SHEEP_DEF)

Binary file not shown.

Binary file not shown.

Binary file not shown.

88
spawn.lua Normal file
View File

@ -0,0 +1,88 @@
-- hostile mobs
if not minetest.setting_getbool("only_peaceful_mobs") then
-- zombie
minetest.register_abm({
nodenames = creatures.z_spawn_nodes,
interval = 40.0,
chance = 7600,
action = function(pos, node, active_object_count, active_object_count_wider)
local n = minetest.get_node_or_nil(pos)
--if n and n.name and n.name ~= "default:stone" and math.random(1,4)>3 then return end
pos.y = pos.y+1
local ll = minetest.env:get_node_light(pos)
local wtime = minetest.env:get_timeofday()
if not ll then
return
end
if ll >= creatures.z_ll then
return
end
if ll < -1 then
return
end
if minetest.env:get_node(pos).name ~= "air" then
return
end
pos.y = pos.y+1
if minetest.env:get_node(pos).name ~= "air" then
return
end
creatures.spawn(pos, 1, "creatures:zombie", 2, 20)
end})
-- ghost
minetest.register_abm({
nodenames = creatures.g_spawn_nodes,
interval = 44.0,
chance = 8350,
action = function(pos, node, active_object_count, active_object_count_wider)
if pos.y < 0 then return end
pos.y = pos.y+1
local ll = minetest.env:get_node_light(pos)
local wtime = minetest.env:get_timeofday()
if not ll then
return
end
if ll >= creatures.g_ll then
return
end
if ll < -1 then
return
end
if minetest.env:get_node(pos).name ~= "air" then
return
end
pos.y = pos.y+1
if minetest.env:get_node(pos).name ~= "air" then
return
end
if (wtime > 0.2 and wtime < 0.805) then
return
end
creatures.spawn(pos, 1, "creatures:ghost", 2, 35)
end})
end
-- peaceful
minetest.register_abm({
nodenames = creatures.s_spawn_nodes,
interval = 55.0,
chance = 7800,
action = function(pos, node, active_object_count, active_object_count_wider)
if pos.y < 0 then return end
pos.y = pos.y+1
local ll = minetest.env:get_node_light(pos) or 0
if ll < 14 then return end
local wtime = minetest.env:get_timeofday()
if minetest.env:get_node(pos).name ~= "air" then
return
end
if minetest.env:get_node(pos).name ~= "air" then
return
end
if (wtime < 0.2 and wtime > 0.805) then
return
end
if math.random(1,10) > 8 then return end
creatures.spawn(pos, math.random(1,2), "creatures:sheep", 5, 35)
end})

94
spawners.lua Normal file
View File

@ -0,0 +1,94 @@
function creatures.register_spawner(mob,size,offset,mesh,texture,range,max,max_ll,min_ll,day_only)
local DUMMY = {
hp_max = 1,
physical = true,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
visual_size = size,
mesh = mesh,
textures = texture,
makes_footstep_sound = false,
timer = 0,
automatic_rotate = math.pi * -2.9,
m_name = "dummy"
}
DUMMY.on_activate = function(self)
self.object:setvelocity({x=0, y=0, z=0})
self.object:setacceleration({x=0, y=0, z=0})
self.object:set_armor_groups({immortal=1})
end
DUMMY.on_step = function(self, dtime)
self.timer = self.timer + 0.01
local n = minetest.get_node_or_nil(self.object:getpos())
if self.timer > 1 then
if n and n.name and n.name ~= "creatures:"..mob.."_spawner" then
self.object:remove()
end
end
end
DUMMY.on_punch = function(self, hitter)
end
minetest.register_entity("creatures:dummy_"..mob, DUMMY)
-- node
minetest.register_node("creatures:"..mob.."_spawner", {
description = mob.." spawner",
paramtype = "light",
tiles = {"creatures_spawner.png"},
is_ground_content = true,
drawtype = "allfaces",
groups = {cracky=1,level=1},
drop = "",
on_construct = function(pos)
pos.y = pos.y + offset
minetest.env:add_entity(pos,"creatures:dummy_"..mob)
end,
on_destruct = function(pos)
for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, 1)) do
if not obj:is_player() then
if obj ~= nil and obj:get_luaentity().m_name == "dummy" then
obj:remove()
end
end
end
end
})
--abm
minetest.register_abm({
nodenames = {"creatures:"..mob.."_spawner"},
interval = 2.0,
chance = 20,
action = function(pos, node, active_object_count, active_object_count_wider)
local res,player_near = false
local mobs = 0
res,mobs,player_near = creatures.find_mates(pos, mob, range)
if player_near then
if mobs < max then
pos.x = pos.x+1
local p = minetest.find_node_near(pos, 5, {"air"})
local ll = minetest.env:get_node_light(p)
local wtime = minetest.env:get_timeofday()
if not ll then return end
if ll > max_ll then return end
if ll < min_ll then return end
if minetest.env:get_node(p).name ~= "air" then return end
p.y = p.y+1
if minetest.env:get_node(p).name ~= "air" then return end
if not day_only then
if (wtime > 0.2 and wtime < 0.805) and pos.y > 0 then return end
end
p.y = p.y-1
creatures.spawn(p, 1, "creatures:"..mob,range,max)
end
end
end })
end
-- spawner
creatures.register_spawner("zombie",{x=0.42,y=0.42},0.08,"creatures_mob.x",{"creatures_zombie.png"},17,6,7,-1,false)
creatures.register_spawner("sheep",{x=0.42,y=0.42},-0.3,"creatures_sheep.x",{"creatures_sheep.png"},17,6,18,10,true)

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

View File

@ -1,10 +1,3 @@
minetest.register_craftitem("creatures:rotten_flesh", {
description = "Rotten Flesh",
inventory_image = "creatures_rotten_flesh.png",
on_use = minetest.item_eat(1),
})
local z_chillaxin_speed = 1.5
local z_animation_speed = 15
local z_mesh = "creatures_mob.x"
@ -14,15 +7,15 @@ local z_drop = "creatures:rotten_flesh"
local z_player_radius = 14
local z_hit_radius = 1.4
local z_ll = 7
creatures.z_ll = 7
local z_sound_normal = "creatures_zombie"
local z_sound_hit = "creatures_zombie_hit"
local z_sound_dead = "creatures_zombie_death"
local z_spawn_nodes = {"default:dirt_with_grass","default:stone","default:dirt","default:desert_sand"}
local z_spawner_range = 17
local z_spawner_max_mobs = 6
creatures.z_spawn_nodes = {"default:dirt_with_grass","default:stone","default:dirt","default:desert_sand"}
creatures.z_spawner_range = 17
creatures.z_spawner_max_mobs = 6
local function z_get_animations()
return {
@ -38,13 +31,6 @@ local function z_get_animations()
}
end
local ANIM_STAND = 1
local ANIM_SIT = 2
local ANIM_LAY = 3
local ANIM_WALK = 4
local ANIM_WALK_MINE = 5
local ANIM_MINE = 6
function z_hit(self)
local sound = z_sound_hit
if self.object:get_hp() < 1 then sound = z_sound_dead end
@ -95,40 +81,6 @@ ZOMBIE_DEF = {
mob_name = "zombie"
}
spawner_DEF = {
hp_max = 1,
physical = true,
collisionbox = {0,0,0,0,0,0},
visual = "mesh",
visual_size = {x=0.42,y=0.42},
mesh = z_mesh,
textures = z_texture,
makes_footstep_sound = false,
timer = 0,
automatic_rotate = math.pi * -2.9,
m_name = "dummy"
}
spawner_DEF.on_activate = function(self)
z_update_visuals_def(self)
self.object:setvelocity({x=0, y=0, z=0})
self.object:setacceleration({x=0, y=0, z=0})
self.object:set_armor_groups({immortal=1})
end
spawner_DEF.on_step = function(self, dtime)
self.timer = self.timer + 0.01
local n = minetest.get_node_or_nil(self.object:getpos())
if self.timer > 1 then
if n and n.name and n.name ~= "creatures:zombie_spawner" then
self.object:remove()
end
end
end
spawner_DEF.on_punch = function(self, hitter)
end
ZOMBIE_DEF.on_activate = function(self)
z_update_visuals_def(self)
self.anim = z_get_animations()
@ -161,24 +113,13 @@ ZOMBIE_DEF.on_punch = function(self, puncher, time_from_last_punch, tool_capabil
elseif self.state >= 2 then
self.state = 9
end
--add wear to swords
if not minetest.setting_getbool("creative_mode") then
local item = puncher:get_wielded_item()
local def = item:get_definition()
if def and def.tool_capabilities and def.tool_capabilities.groupcaps
and def.tool_capabilities.groupcaps.snappy then
local uses = def.tool_capabilities.groupcaps.snappy.uses or 10
uses = uses*2 --since default values are too low
local wear = 65535/uses
item:add_wear(wear)
puncher:set_wielded_item(item)
end
end
-- add wear to sword/tool
creatures.add_wear(puncher, tool_capabilities)
end
end
if self.object:get_hp() < 1 then
local obj = minetest.env:add_item(my_pos, z_drop.." "..math.random(0,3))
creatures.drop(my_pos, {{name=z_drop, count=math.random(0,2)}}, dir)
end
end
@ -192,7 +133,7 @@ ZOMBIE_DEF.on_step = function(self, dtime)
self.sound_timer = self.sound_timer + 0.01
local current_pos = self.object:getpos()
local current_node = minetest.env:get_node(current_pos)
local current_node = minetest.env:get_node_or_nil(current_pos)
if self.time_passed == nil then
self.time_passed = 0
end
@ -207,18 +148,22 @@ ZOMBIE_DEF.on_step = function(self, dtime)
minetest.sound_play(z_sound_dead, {pos = current_pos, max_hear_distance = 10, gain = 0.9})
self.object:set_animation({x=self.anim.lay_START,y=self.anim.lay_END}, z_animation_speed, 0)
minetest.after(1, function()
self.object:remove()
local obj = minetest.env:add_item(current_pos, z_drop.." "..math.random(0,3))
self.object:remove()
if self.object:get_hp() < 1 then
creatures.drop(current_pos, {{name=z_drop, count=math.random(0,2)}})
end
end)
end
-- die when in water, lava or sunlight
local wtime = minetest.env:get_timeofday()
local ll = minetest.env:get_node_light({x=current_pos.x,y=current_pos.y+1,z=current_pos.z}) or 0
if current_node.name == "default:water_source" or
current_node.name == "default:water_flowing" or
current_node.name == "default:lava_source" or
current_node.name == "default:lava_flowing" or
local nn = nil
if current_node ~= nil then nn = current_node.name end
if nn ~= nil and nn == "default:water_source" or
nn == "default:water_flowing" or
nn == "default:lava_source" or
nn == "default:lava_flowing" or
(wtime > 0.2 and wtime < 0.805 and current_pos.y > 0 and ll > 11) then
self.sound_timer = self.sound_timer + dtime
if self.sound_timer >= 0.8 then
@ -282,17 +227,17 @@ ZOMBIE_DEF.on_step = function(self, dtime)
end
end
if self.attacker == "" and self.turn_timer > math.random(1,4) then--and yawwer == true then
if self.attacker == "" and self.turn_timer > math.random(1,4) then
self.yaw = 360 * math.random()
self.object:setyaw(self.yaw)
self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
end
self.object:setvelocity({x=0,y=self.object:getvelocity().y,z=0})
if self.npc_anim ~= ANIM_STAND then
if self.npc_anim ~= creatures.ANIM_STAND then
self.anim = z_get_animations()
self.object:set_animation({x=self.anim.stand_START,y=self.anim.stand_END}, z_animation_speed, 0)
self.npc_anim = ANIM_STAND
self.npc_anim = creatures.ANIM_STAND
end
if self.attacker ~= "" then
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
@ -333,8 +278,7 @@ ZOMBIE_DEF.on_step = function(self, dtime)
if self.state == 2 then
if self.attacker ~= "" then
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
--self.state = 2
self.direction = {x=math.sin(self.yaw)*-1, y=-20, z=math.cos(self.yaw)}
end
if self.direction ~= nil then
self.object:setvelocity({x=self.direction.x*z_chillaxin_speed,y=self.object:getvelocity().y,z=self.direction.z*z_chillaxin_speed})
@ -343,25 +287,21 @@ ZOMBIE_DEF.on_step = function(self, dtime)
self.yaw = 360 * math.random()
self.object:setyaw(self.yaw)
self.turn_timer = 0
self.direction = {x = math.sin(self.yaw)*-1, y = -20, z = math.cos(self.yaw)}
self.direction = {x=math.sin(self.yaw)*-1, y=-20, z=math.cos(self.yaw)}
end
if self.npc_anim ~= ANIM_WALK then
self.npc_anim = ANIM_WALK
--self.anim = z_get_animations()
if self.npc_anim ~= creatures.ANIM_WALK then
self.npc_anim = creatures.ANIM_WALK
self.object:set_animation({x=self.anim.walk_START,y=self.anim.walk_END}, z_animation_speed, 0)
self.npc_anim = ANIM_WALK
end
--jump
if self.direction ~= nil then
if self.jump_timer > 0.3 then
if self.jump_timer > 0.25 then
self.jump_timer = 0
local p = current_pos
local n = minetest.env:get_node({x=p.x + self.direction.x,y=p.y-0.5,z=p.z + self.direction.z})
--print(n.name)
if n and n.name and minetest.registered_items[n.name].walkable then
self.object:setvelocity({x=self.object:getvelocity().x,y=7,z=self.object:getvelocity().z})
local n = minetest.env:get_node_or_nil({x=p.x + self.direction.x,y=p.y-0.5,z=p.z + self.direction.z})
if n and n.name and minetest.registered_items[n.name].walkable and minetest.registered_items[n.name].groups.fences == nil and n.name ~= "default:fence_wood" then
self.object:setvelocity({x=self.object:getvelocity().x,y=7.1,z=self.object:getvelocity().z})
end
--end
end
end
@ -384,115 +324,3 @@ ZOMBIE_DEF.on_step = function(self, dtime)
end
minetest.register_entity("creatures:zombie", ZOMBIE_DEF)
minetest.register_entity("creatures:z_spawner_mob", spawner_DEF)
--spawn-egg/spawner
minetest.register_craftitem("creatures:zombie_spawn_egg", {
description = "Zombie spawn-egg",
inventory_image = "creatures_egg_zombie.png",
liquids_pointable = false,
stack_max = 99,
on_place = function(itemstack, placer, pointed_thing)
if pointed_thing.type == "node" then
local p = pointed_thing.above
p.y = p.y+1
creatures.spawn(p, 1, "creatures:zombie")
if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end
return itemstack
end
end,
})
minetest.register_node("creatures:zombie_spawner", {
description = "Zombie spawner",
paramtype = "light",
tiles = {"creatures_spawner.png"},
is_ground_content = true,
drawtype = "allfaces",
groups = {cracky=1,level=1},
drop = "",
on_construct = function(pos)
pos.y = pos.y + 0.08
minetest.env:add_entity(pos,"creatures:z_spawner_mob")
end,
on_destruct = function(pos)
for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, 1)) do
if not obj:is_player() then
if obj ~= nil and obj:get_luaentity().m_name == "dummy" then
obj:remove()
end
end
end
end
})
if not minetest.setting_getbool("only_peaceful_mobs") then
-- spawn randomly in world
minetest.register_abm({
nodenames = z_spawn_nodes,
interval = 40.0,
chance = 7200,
action = function(pos, node, active_object_count, active_object_count_wider)
local n = minetest.get_node(pos)
--if n and n.name and n.name ~= "default:stone" and math.random(1,4)>3 then return end
pos.y = pos.y+1
local ll = minetest.env:get_node_light(pos)
local wtime = minetest.env:get_timeofday()
if not ll then
return
end
if ll >= z_ll then
return
end
if ll < -1 then
return
end
if minetest.env:get_node(pos).name ~= "air" then
return
end
pos.y = pos.y+1
if minetest.env:get_node(pos).name ~= "air" then
return
end
creatures.spawn(pos, 1, "creatures:zombie")
end
})
minetest.register_abm({
nodenames = {"creatures:zombie_spawner"},
interval = 2.0,
chance = 20,
action = function(pos, node, active_object_count, active_object_count_wider)
local player_near = false
local mobs = 0
for _,obj in ipairs(minetest.env:get_objects_inside_radius(pos, z_spawner_range)) do
if obj:is_player() then
player_near = true
else
if obj:get_luaentity().mob_name == "zombie" then mobs = mobs + 1 end
end
end
if player_near then
if mobs < z_spawner_max_mobs then
pos.x = pos.x+1
local p = minetest.find_node_near(pos, 5, {"air"})
--p.y = p.y+1
local ll = minetest.env:get_node_light(p)
local wtime = minetest.env:get_timeofday()
if not ll then return end
if ll > 8 then return end
if ll < -1 then return end
if minetest.env:get_node(p).name ~= "air" then return end
p.y = p.y+1
if minetest.env:get_node(p).name ~= "air" then return end
if (wtime > 0.2 and wtime < 0.805) and pos.y > 0 then return end
p.y = p.y-1
creatures.spawn(p, 1, "creatures:zombie")
end
end
end
})
end