master
Mathis 2017-03-30 17:20:56 +02:00
parent 5baf4023d1
commit f67942b506
25 changed files with 65 additions and 1799 deletions

View File

@ -1,20 +0,0 @@
engine:Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
poketest:Copyright (c) 2017 MBB <MBB@webproxy.li>
This software is provided 'as-is', without any express or implied warranty. In no
event will the authors be held liable for any damages arising from the use of
this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to the
following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation is required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -1,36 +0,0 @@
Mod/Modpack Creatures
=====================
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
Version: 2.3.1
A Mod(pack) for Minetest that provides a MOB-Engine and adds several creatures to the game.
Currently included: Ghosts, Zombies, Sheep, Chicken and Oerrki.
License:
~~~~~~~~
Code(if not stated differently):
(c) Copyright 2015-2016 BlockMen; modified zlib-License
see "LICENSE.txt" for details.
Media(if not stated differently):
(c) Copyright (2014-2016) BlockMen; CC-BY-SA 3.0
see each MOB-Module for detailed informations.
Github:
~~~~~~~
https://github.com/BlockMen/cme
Forum:
~~~~~~
https://forum.minetest.net/viewtopic.php?id=8638
Changelog:
~~~~~~~~~~
see Changelog.txt

View File

@ -1,20 +0,0 @@
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no
event will the authors be held liable for any damages arising from the use of
this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to the
following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation is required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -1,26 +0,0 @@
Creatures MOB-Engine
====================
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
Version: 2.0.2
This mod provides an engine, that handles the base function for MOB in Minetest.
It offers an easy way to register MOB and allows to custom handling for the needs
of each mob. This engine aims to be a solid base, that has a good balance between
performance and functionality.
See API.txt for more informations on how to use this engine for mobs.
License:
~~~~~~~~
Code:
(c) Copyright 2015-2016 BlockMen; modified zlib-License
see "LICENSE.txt" for details.
Media(textures and other media):
(c) Copyright (2014-2016) BlockMen; CC-BY-SA 3.0
Github:
~~~~~~~
https://github.com/BlockMen/cme/creatures

View File

@ -1,148 +0,0 @@
--= Creatures MOB-Engine (cme) =--
-- Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
--
-- common.lua
--
-- This software is provided 'as-is', without any express or implied warranty. In no
-- event will the authors be held liable for any damages arising from the use of
-- this software.
--
-- Permission is granted to anyone to use this software for any purpose, including
-- commercial applications, and to alter it and redistribute it freely, subject to the
-- following restrictions:
--
-- 1. The origin of this software must not be misrepresented; you must not
-- claim that you wrote the original software. If you use this software in a
-- product, an acknowledgment in the product documentation is required.
-- 2. Altered source versions must be plainly marked as such, and must not
-- be misrepresented as being the original software.
-- 3. This notice may not be removed or altered from any source distribution.
--
-- constants
nullVec = {x = 0, y = 0, z = 0}
DEGTORAD = math.pi / 180.0
-- common functions
function creatures.rnd(table, errval)
if not errval then
errval = false
end
local res = 1000000000
local rn = math.random(0, res - 1)
local retval = nil
local psum = 0
for s,w in pairs(table) do
psum = psum + ((tonumber(w) or w.chance or 0) * res)
if psum > rn then
retval = s
break
end
end
return retval
end
function throw_error(msg)
core.log("error", "#Creatures: ERROR: " .. msg)
end
function creatures.compare_pos(pos1, pos2)
if not pos1 or not pos2 then
return
end
if pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z then
return false
end
return true
end
function creatures.findTarget(search_obj, pos, radius, search_type, ignore_mob, xray, no_count)
local player_near = false
local mobs = {}
for _,obj in ipairs(core.get_objects_inside_radius(pos, radius)) do
if obj ~= search_obj then
if xray or core.line_of_sight(pos, obj:getpos()) == true then
local is_player = obj:is_player()
if is_player then
player_near = true
if no_count == true then
return {}, true
end
end
local entity = obj:get_luaentity()
local isItem = (entity and entity.name == "__builtin:item") or false
local ignore = (entity and entity.mob_name == ignore_mob and search_type ~= "mates") or false
if search_type == "all" then
if not isItem and not ignore then
table.insert(mobs, obj)
end
elseif search_type == "hostile" then
if not ignore and (entity and entity.hostile == true) or is_player then
table.insert(mobs, obj)
end
elseif search_type == "nonhostile" then
if entity and not entity.hostile and not isItem and not ignore then
table.insert(mobs, obj)
end
elseif search_type == "player" then
if is_player then
table.insert(mobs, obj)
end
elseif search_type == "mate" then
if not isItem and (entity and entity.mob_name == ignore_mob) then
table.insert(mobs, obj)
end
end
end
end --for
end
return mobs,player_near
end
function creatures.dropItems(pos, drops)
if not pos or not drops then
return
end
-- convert drops table
local tab = {}
for _,elem in pairs(drops) do
local name = tostring(elem[1])
local v = elem[2]
local chance = elem.chance
local amount = ""
-- check if drops depending on defined chance
if name and chance then
local ct = {}
ct[name] = chance
ct["_fake"] = 1 - chance
local res = creatures.rnd(ct)
if res == "_fake" then
name = nil
end
end
-- get amount
if name and v then
if type(v) == "table" then
amount = math.random(v.min or 1, v.max or 1) or 1
elseif type(v) == "number" then
amount = v
end
if amount > 0 then
amount = " " .. amount
end
end
if name then
local obj = core.add_item(pos, name .. amount)
if not obj then
throw_error("Could not drop item '" .. name .. amount .. "'")
end
end
end
end

View File

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

View File

@ -1 +0,0 @@
A Mod(pack) for Minetest that provides a MOB-Engine and adds several creatures to the game.

View File

@ -1,674 +0,0 @@
--= Creatures MOB-Engine (cme) =--
-- Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
--
-- functions.lua
--
-- This software is provided 'as-is', without any express or implied warranty. In no
-- event will the authors be held liable for any damages arising from the use of
-- this software.
--
-- Permission is granted to anyone to use this software for any purpose, including
-- commercial applications, and to alter it and redistribute it freely, subject to the
-- following restrictions:
--
-- 1. The origin of this software must not be misrepresented; you must not
-- claim that you wrote the original software. If you use this software in a
-- product, an acknowledgment in the product documentation is required.
-- 2. Altered source versions must be plainly marked as such, and must not
-- be misrepresented as being the original software.
-- 3. This notice may not be removed or altered from any source distribution.
--
-- Localizations
local rnd = math.random
local function knockback(selfOrObject, dir, old_dir, strengh)
local object = selfOrObject
if selfOrObject.mob_name then
object = selfOrObject.object
end
local current_fmd = object:get_properties().automatic_face_movement_dir or 0
object:set_properties({automatic_face_movement_dir = false})
object:setvelocity(vector.add(old_dir, {x = dir.x * strengh, y = 3.5, z = dir.z * strengh}))
old_dir.y = 0
core.after(0.4, function()
object:set_properties({automatic_face_movement_dir = current_fmd})
object:setvelocity(old_dir)
selfOrObject.falltimer = nil
if selfOrObject.stunned == true then
selfOrObject.stunned = false
if selfOrObject.can_panic == true then
selfOrObject.target = nil
selfOrObject.mode = "_run"
selfOrObject.modetimer = 0
end
end
end)
end
local function on_hit(me)
core.after(0.1, function()
me:settexturemod("^[colorize:#c4000099")
end)
core.after(0.5, function()
me:settexturemod("")
end)
end
local hasMoved = creatures.compare_pos
local function getDir(pos1, pos2)
local retval
if pos1 and pos2 then
retval = {x = pos2.x - pos1.x, y = pos2.y - pos1.y, z = pos2.z - pos1.z}
end
return retval
end
local function getDistance(vec, fly_offset)
if not vec then
return -1
end
if fly_offset then
vec.y = vec.y + fly_offset
end
return math.sqrt((vec.x)^2 + (vec.y)^2 + (vec.z)^2)
end
local findTarget = creatures.findTarget
local function update_animation(obj_ref, mode, anim_def)
if anim_def and obj_ref then
obj_ref:set_animation({x = anim_def.start, y = anim_def.stop}, anim_def.speed, 0, anim_def.loop)
end
end
local function update_velocity(obj_ref, dir, speed, add)
local velo = obj_ref:getvelocity()
if not dir.y then
dir.y = velo.y/speed
end
local new_velo = {x = dir.x * speed, y = dir.y * speed or velo.y , z = dir.z * speed}
if add then
new_velo = vector.add(velo, new_velo)
end
obj_ref:setvelocity(new_velo)
end
local function getYaw(dirOrYaw)
local yaw = 360 * rnd()
if dirOrYaw and type(dirOrYaw) == "table" then
yaw = math.atan(dirOrYaw.z / dirOrYaw.x) + math.pi^2 - 2
if dirOrYaw.x > 0 then
yaw = yaw + math.pi
end
elseif dirOrYaw and type(dirOrYaw) == "number" then
-- here could be a value based on given yaw
end
return yaw
end
local dropItems = creatures.dropItems
local function killMob(me, def)
if not def then
if me then
me:remove()
end
end
local pos = me:getpos()
me:setvelocity(nullVec)
me:set_properties({collisionbox = nullVec})
me:set_hp(0)
if def.sounds and def.sounds.on_death then
local death_snd = def.sounds.on_death
core.sound_play(death_snd.name, {pos = pos, max_hear_distance = death_snd.distance or 5, gain = death_snd.gain or 1})
end
if def.model.animations.death then
local dur = def.model.animations.death.duration or 0.5
update_animation(me, "death", def.model.animations["death"])
core.after(dur, function()
me:remove()
end)
else
me:remove()
end
if def.drops then
if type(def.drops) == "function" then
def.drops(me:get_luaentity())
else
dropItems(pos, def.drops)
end
end
end
local function limit(value, min, max)
if value < min then
return min
end
if value > max then
return max
end
return value
end
local function calcPunchDamage(obj, actual_interval, tool_caps)
local damage = 0
if not tool_caps or not actual_interval then
return 0
end
local my_armor = obj:get_armor_groups() or {}
for group,_ in pairs(tool_caps.damage_groups) do
damage = damage + (tool_caps.damage_groups[group] or 0) * limit(actual_interval / tool_caps.full_punch_interval, 0.0, 1.0) * ((my_armor[group] or 0) / 100.0)
end
return damage or 0
end
local function onDamage(self, hp)
local me = self.object
local def = core.registered_entities[self.mob_name]
hp = hp or me:get_hp()
if hp <= 0 then
self.stunned = true
killMob(me, def)
else
on_hit(me) -- red flashing
if def.sounds and def.sounds.on_damage then
local dmg_snd = def.sounds.on_damage
core.sound_play(dmg_snd.name, {pos = me:getpos(), max_hear_distance = dmg_snd.distance or 5, gain = dmg_snd.gain or 1})
end
end
end
local function changeHP(self, value)
local me = self.object
local hp = me:get_hp()
hp = hp + math.floor(value)
me:set_hp(hp)
if value < 0 then
onDamage(self, hp)
end
end
local function checkWielded(wielded, itemList)
for s,w in pairs(itemList) do
if w == wielded then
return true
end
end
return false
end
local tool_uses = {0, 30, 110, 150, 280, 300, 500, 1000}
local function addWearout(player, tool_def)
if not core.setting_getbool("creative_mode") then
local item = player:get_wielded_item()
if tool_def and tool_def.damage_groups and tool_def.damage_groups.fleshy then
local uses = tool_uses[tool_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
local function spawnParticles(...)
end
if core.setting_getbool("creatures_enable_particles") == true then
spawnParticles = function(pos, velocity, texture_str)
local vel = vector.multiply(velocity, 0.5)
vel.y = 0
core.add_particlespawner({
amount = 8,
time = 1,
minpos = vector.add(pos, -0.7),
maxpos = vector.add(pos, 0.7),
minvel = vector.add(vel, {x = -0.1, y = -0.01, z = -0.1}),
maxvel = vector.add(vel, {x = 0.1, y = 0, z = 0.1}),
minacc = vector.new(),
maxacc = vector.new(),
minexptime = 0.8,
maxexptime = 1,
minsize = 1,
maxsize = 2.5,
texture = texture_str,
})
end
end
-- --
-- Default entity functions
-- --
creatures.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if self.stunned == true then
return
end
local me = self.object
local mypos = me:getpos()
changeHP(self, calcPunchDamage(me, time_from_last_punch, tool_capabilities) * -1)
if puncher then
if self.hostile then
self.mode = "attack"
self.target = puncher
end
if time_from_last_punch >= 0.45 and self.stunned == false then
if self.has_kockback == true then
local v = me:getvelocity()
v.y = 0
if not self.can_fly then
me:setacceleration({x = 0, y = -15, z = 0})
end
knockback(self, dir, v, 5)
self.stunned = true
end
-- add wearout to weapons/tools
addWearout(puncher, tool_capabilities)
end
end
end
creatures.on_rightclick = function(self, clicker)
end
creatures.on_step = function(self, dtime)
-- first get the relevant specs; exit if we don't know anything (1-3ms)
local def = core.registered_entities[self.mob_name]
if not def then
throw_error("Can't load creature-definition")
return
end
-- timer updates
self.lifetimer = self.lifetimer + dtime
self.modetimer = self.modetimer + dtime
self.soundtimer = self.soundtimer + dtime
self.yawtimer = self.yawtimer + dtime
self.nodetimer = self.nodetimer + dtime
self.followtimer = self.followtimer + dtime
if self.envtimer then
self.envtimer = self.envtimer + dtime
end
if self.falltimer then
self.falltimer = self.falltimer + dtime
end
if self.searchtimer then
self.searchtimer = self.searchtimer + dtime
end
if self.attacktimer then
self.attacktimer = self.attacktimer + dtime
end
if self.swimtimer then
self.swimtimer = self.swimtimer + dtime
end
-- main
if self.stunned == true then
return
end
if self.lifetimer > def.stats.lifetime and not (self.mode == "attack" and self.target) then
self.lifetimer = 0
if not self.tamed or (self.tamed and def.stats.dies_when_tamed) then
killMob(self.object, def)
end
end
-- localize some things
local modes = def.modes
local current_mode = self.mode
local me = self.object
local current_pos = me:getpos()
current_pos.y = current_pos.y + 0.5
local moved = hasMoved(current_pos, self.last_pos) or false
local fallen = false
-- Update pos and current node if necessary
if moved == true or not self.last_pos then
-- for falldamage
if self.has_falldamage and self.last_pos and not self.in_water then
local dist = math.abs(current_pos.y - self.last_pos.y)
if dist > 0 then
self.fall_dist = self.fall_dist - dist
if not self.falltimer then
self.falltimer = 0
end
end
end
self.last_pos = current_pos
if self.nodetimer > 0.2 then
self.nodetimer = 0
local current_node = core.get_node_or_nil(current_pos)
self.last_node = current_node
if def.stats.light then
local wtime = core.get_timeofday()
local llvl = core.get_node_light({x = current_pos.x, y = current_pos.y + 0.5, z = current_pos.z}) or 0
self.last_llvl = llvl
end
end
else
if (modes[current_mode].moving_speed or 0) > 0 then
update_velocity(me, nullVec, 0)
if modes["idle"] and not (current_mode == "attack" or current_mode == "follow") then
current_mode = "idle"
self.modetimer = 0
end
end
if self.fall_dist < 0 then
fallen = true
end
end
if fallen then
local falltime = tonumber(self.falltimer) or 0
local dist = math.abs(self.fall_dist) or 0
self.falltimer = 0
self.fall_dist = 0
fallen = false
local damage = 0
if dist > 3 and not self.in_water and falltime/dist < 0.2 then
damage = dist - 3
end
-- damage by calced value
if damage > 0 then
changeHP(self, damage * -1)
end
end
-- special mode handling
-- check distance to target
if self.target and self.followtimer > 0.6 then
self.followtimer = 0
local p2 = self.target:getpos()
local dir = getDir(current_pos, p2)
local offset
if self.can_fly then
offset = modes["fly"].target_offset
end
local dist = getDistance(dir, offset)
local radius
if self.hostile and def.combat then
radius = def.combat.search_radius
elseif modes["follow"] then
radius = modes["follow"].radius
end
if dist == -1 or dist > (radius or 5) then
self.target = nil
current_mode = ""
elseif dist > -1 and self.hostile and dist < def.combat.attack_radius then
-- attack
if self.attacktimer > def.combat.attack_speed then
self.attacktimer = 0
if core.line_of_sight(current_pos, p2) == true then
self.target:punch(me, 1.0, {
full_punch_interval = def.combat.attack_speed,
damage_groups = {fleshy = def.combat.attack_damage}
})
end
update_velocity(me, self.dir, 0)
end
else
if current_mode == "attack" or current_mode == "follow" then
self.dir = vector.normalize(dir)
me:setyaw(getYaw(dir))
if self.in_water then
self.dir.y = me:getvelocity().y
end
update_velocity(me, self.dir, modes[current_mode].moving_speed or 0)
end
end
end
-- search a target (1-2ms)
if not self.target and ((self.hostile and def.combat.search_enemy) or modes["follow"]) and current_mode ~= "_run" then
local timer
if self.hostile then
timer = def.combat.search_timer or 2
elseif modes["follow"] then
timer = modes["follow"].timer
end
if self.searchtimer > (timer or 4) then
self.searchtimer = 0
local targets = {}
if self.hostile then
targets = findTarget(me, current_pos, def.combat.search_radius, def.combat.search_type, def.combat.search_xray)
else
targets = findTarget(me, current_pos, modes["follow"].radius or 5, "player")
end
if #targets > 1 then
self.target = targets[rnd(1, #targets)]
elseif #targets == 1 then
self.target = targets[1]
end
if self.target then
if self.hostile and modes["attack"] then
current_mode = "attack"
else
local name = self.target:get_wielded_item():get_name()
if name and checkWielded(name, modes["follow"].items) == true then
current_mode = "follow"
self.modetimer = 0
else
self.target = nil
end
end
end
end
end
if current_mode == "eat" and not self.eat_node then
local nodes = modes[current_mode].nodes
local p = {x = current_pos.x, y = current_pos.y - 1, z = current_pos.z}
local sn = core.get_node_or_nil(p)
local eat_node
for _,name in pairs(nodes) do
if name == self.last_node.name then
eat_node = current_pos
break
elseif sn and sn.name == name then
eat_node = p
break
end
end
if not eat_node then
current_mode = "idle"
else
self.eat_node = eat_node
end
end
-- further mode handling
-- update mode
if current_mode ~= "attack" and
(current_mode == "" or self.modetimer > (modes[current_mode].duration or 4)) then
self.modetimer = 0
local new_mode = creatures.rnd(modes) or "idle"
if new_mode == "eat" and self.in_water == true then
new_mode = "idle"
end
if current_mode == "follow" and rnd(1, 10) < 3 then
new_mode = current_mode
elseif current_mode == "follow" then
-- "lock" searching a little bit
self.searchtimer = rnd(5, 8) * -1
self.target = nil
end
current_mode = new_mode
-- change eaten node when mode changes
if self.eat_node then
local n = core.get_node_or_nil(self.eat_node)
local nnn = n.name
local def = core.registered_nodes[n.name]
local sounds
if def then
if def.drop and type(def.drop) == "string" then
nnn = def.drop
elseif not def.walkable then
nnn = "air"
end
end
if nnn and nnn ~= n.name and core.registered_nodes[nnn] then
core.set_node(self.eat_node, {name = nnn})
if not sounds then
sounds = def.sounds
end
if sounds and sounds.dug then
core.sound_play(sounds.dug, {pos = self.eat_node, max_hear_distance = 5, gain = 1})
end
end
self.eat_node = nil
end
end
-- mode has changes, do things
if current_mode ~= self.last_mode then
self.last_mode = current_mode
local moving_speed = modes[current_mode].moving_speed or 0
if moving_speed > 0 then
local yaw = (getYaw(me:getyaw()) + 90.0) * DEGTORAD
me:setyaw(yaw + 4.73)
self.dir = {x = math.cos(yaw), y = 0, z = math.sin(yaw)}
if self.can_fly then
if current_pos.y >= (modes["fly"].max_height or 50) and not self.target then
self.dir.y = -0.5
else
self.dir.y = (rnd() - 0.5)
end
end
-- reduce speed in water
if self.in_water == true then
moving_speed = moving_speed * 0.7
end
else
self.dir = nullVec
end
update_velocity(me, self.dir, moving_speed)
local anim_def = def.model.animations[current_mode]
if self.in_water and def.model.animations["swim"] then
anim_def = def.model.animations["swim"]
end
update_animation(me, current_mode, anim_def)
end
-- update yaw
if current_mode ~= "attack" and current_mode ~= "follow" and
(modes[current_mode].update_yaw or 0) > 0 and
self.yawtimer > (modes[current_mode].update_yaw or 4) then
self.yawtimer = 0
local mod = nil
if current_mode == "_run" then
mod = me:getyaw()
end
local yaw = (getYaw(mod) + 90.0) * DEGTORAD
me:setyaw(yaw + 4.73)
local moving_speed = modes[current_mode].moving_speed or 0
if moving_speed > 0 then
self.dir = {x = math.cos(yaw), y = nil, z = math.sin(yaw)}
update_velocity(me, self.dir, moving_speed)
end
end
--swim
if self.can_swim and self.swimtimer > 0.8 and self.last_node then
self.swimtimer = 0
local name = self.last_node.name
if name then
if name == "default:water_source" then
self.air_cnt = 0
local vel = me:getvelocity()
update_velocity(me, {x = vel.x, y = 0.9, z = vel.z}, 1)
me:setacceleration({x = 0, y = -1.2, z = 0})
self.in_water = true
-- play swimming sounds
if def.sounds and def.sounds.swim then
local swim_snd = def.sounds.swim
core.sound_play(swim_snd.name, {pos = current_pos, gain = swim_snd.gain or 1, max_hear_distance = swim_snd.distance or 10})
end
spawnParticles(current_pos, vel, "bubble.png")
else
self.air_cnt = self.air_cnt + 1
if self.in_water == true and self.air_cnt > 5 then
self.in_water = false
if not self.can_fly then
me:setacceleration({x = 0, y = -15, z = 0})
end
end
end
end
end
-- Add damage when drowning or in lava
if self.env_damage and self.envtimer > 1 and self.last_node then
self.envtimer = 0
local name = self.last_node.name
if not self.can_swim and name == "default:water_source" then
changeHP(self, -1)
elseif self.can_burn then
if name == "fire:basic_flame" or name == "default:lava_source" then
changeHP(self, -4)
end
end
-- add damage when light is too bright or too dark
local tod = core.get_timeofday() * 24000
if self.last_llvl and self.can_burn and self.last_llvl > (def.stats.light.max or 15) and tod < 18000 then
changeHP(self, -1)
elseif self.last_llvl and self.last_llvl < (def.stats.light.min or 0) then
changeHP(self, -2)
end
end
-- Random sounds
if def.sounds and def.sounds.random[current_mode] then
local rnd_sound = def.sounds.random[current_mode]
if not self.snd_rnd_time then
self.snd_rnd_time = rnd((rnd_sound.time_min or 5), (rnd_sound.time_max or 35))
end
if rnd_sound and self.soundtimer > self.snd_rnd_time + rnd() then
self.soundtimer = 0
self.snd_rnd_time = nil
core.sound_play(rnd_sound.name, {pos = current_pos, gain = rnd_sound.gain or 1, max_hear_distance = rnd_sound.distance or 30})
end
end
self.mode = current_mode
end
creatures.get_staticdata = function(self)
return {
hp = self.object:get_hp(),
mode = self.mode,
tamed = self.tamed,
modetimer = self.modetimer,
lifetimer = self.lifetimer,
soundtimer = self.soundtimer,
fall_dist = self.fall_dist,
in_water = self.in_water,
}
end

View File

@ -1,33 +0,0 @@
--= Creatures MOB-Engine (cme) =--
-- Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
--
-- init.lua
--
-- This software is provided 'as-is', without any express or implied warranty. In no
-- event will the authors be held liable for any damages arising from the use of
-- this software.
--
-- Permission is granted to anyone to use this software for any purpose, including
-- commercial applications, and to alter it and redistribute it freely, subject to the
-- following restrictions:
--
-- 1. The origin of this software must not be misrepresented; you must not
-- claim that you wrote the original software. If you use this software in a
-- product, an acknowledgment in the product documentation is required.
-- 2. Altered source versions must be plainly marked as such, and must not
-- be misrepresented as being the original software.
-- 3. This notice may not be removed or altered from any source distribution.
--
creatures = {}
local modpath = core.get_modpath("creatures")
-- API and common functions
dofile(modpath .."/common.lua")
dofile(modpath .."/functions.lua")
dofile(modpath .."/register.lua")
-- Common items
dofile(modpath .."/items.lua")

View File

@ -1,39 +0,0 @@
--= Creatures MOB-Engine (cme) =--
-- Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
--
-- items.lua
--
-- This software is provided 'as-is', without any express or implied warranty. In no
-- event will the authors be held liable for any damages arising from the use of
-- this software.
--
-- Permission is granted to anyone to use this software for any purpose, including
-- commercial applications, and to alter it and redistribute it freely, subject to the
-- following restrictions:
--
-- 1. The origin of this software must not be misrepresented; you must not
-- claim that you wrote the original software. If you use this software in a
-- product, an acknowledgment in the product documentation is required.
-- 2. Altered source versions must be plainly marked as such, and must not
-- be misrepresented as being the original software.
-- 3. This notice may not be removed or altered from any source distribution.
--
core.register_craftitem("creatures:flesh", {
description = "Flesh",
inventory_image = "creatures_flesh.png",
on_use = core.item_eat(2),
})
core.register_craftitem("creatures:meat", {
description = "Cooked Meat",
inventory_image = "creatures_meat.png",
on_use = core.item_eat(4),
})
core.register_craft({
type = "cooking",
output = "creatures:meat",
recipe = "creatures:flesh",
})

View File

@ -1,580 +0,0 @@
--= Creatures MOB-Engine (cme) =--
-- Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
--
-- register.lua
--
-- This software is provided 'as-is', without any express or implied warranty. In no
-- event will the authors be held liable for any damages arising from the use of
-- this software.
--
-- Permission is granted to anyone to use this software for any purpose, including
-- commercial applications, and to alter it and redistribute it freely, subject to the
-- following restrictions:
--
-- 1. The origin of this software must not be misrepresented; you must not
-- claim that you wrote the original software. If you use this software in a
-- product, an acknowledgment in the product documentation is required.
-- 2. Altered source versions must be plainly marked as such, and must not
-- be misrepresented as being the original software.
-- 3. This notice may not be removed or altered from any source distribution.
--
local allow_hostile = core.setting_getbool("only_peaceful_mobs") ~= true
local function translate_def(def)
local new_def = {
physical = true,
visual = "mesh",
stepheight = 0.6, -- ensure we get over slabs/stairs
automatic_face_movement_dir = def.model.rotation or 0.0,
mesh = def.model.mesh,
textures = def.model.textures,
collisionbox = def.model.collisionbox or {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
visual_size = def.model.scale or {x = 1, y = 1},
backface_culling = def.model.backface_culling or false,
collide_with_objects = def.model.collide_with_objects or true,
makes_footstep_sound = true,
stats = def.stats,
model = def.model,
sounds = def.sounds,
combat = def.combat,
modes = {},
drops = def.drops,
}
-- Tanslate modes to better accessable format
for mn,def in pairs(def.modes) do
local name = tostring(mn)
if name ~= "update_time" then
new_def.modes[name] = def
--if name == "attack" then new_def.modes[name].chance = 0 end
end
end
-- insert special mode "_run" which is used when in panic
if def.stats.can_panic then
if def.modes.walk then
local new = table.copy(new_def.modes["walk"])
new.chance = 0
new.duration = 3
new.moving_speed = new.moving_speed * 2
if def.modes.panic and def.modes.panic.moving_speed then
new.moving_speed = def.modes.panic.moving_speed
end
new.update_yaw = 0.7
new_def.modes["_run"] = new
local new_anim = def.model.animations.panic
if not new_anim then
new_anim = table.copy(def.model.animations.walk)
new_anim.speed = new_anim.speed * 2
end
new_def.model.animations._run = new_anim
end
end
if def.stats.can_jump and type(def.stats.can_jump) == "number" then
if def.stats.can_jump > 0 then
new_def.stepheight = def.stats.can_jump + 0.1
end
end
if def.stats.sneaky or def.stats.can_fly then
new_def.makes_footstep_sound = false
end
new_def.get_staticdata = function(self)
local main_tab = creatures.get_staticdata(self)
-- is own staticdata function defined? If so, merge results
if def.get_staticdata then
local data = def.get_staticdata(self)
if data and type(data) == "table" then
for s,w in pairs(data) do
main_tab[s] = w
end
end
end
-- return data serialized
return core.serialize(main_tab)
end
new_def.on_activate = function(self, staticdata)
-- Add everything we need as basis for the engine
self.mob_name = def.name
self.hp = def.stats.hp
self.hostile = def.stats.hostile
self.mode = ""
self.stunned = false -- if knocked back or hit do nothing else
self.has_kockback = def.stats.has_kockback
self.has_falldamage = def.stats.has_falldamage
self.can_swim = def.stats.can_swim
self.can_fly = def.stats.can_fly
self.can_burn = def.stats.can_burn
self.can_panic = def.stats.can_panic == true and def.modes.walk ~= nil
--self.is_tamed = nil
--self.target = nil
self.dir = {x = 0, z = 0}
--self.last_pos = nil (was nullVec)
--self.last_node = nil
--self.last_llvl = 0
self.fall_dist = 0
self.air_cnt = 0
-- Timers
self.lifetimer = 0
self.modetimer = math.random()--0
self.soundtimer = math.random()
self.nodetimer = 2 -- ensure we get the first step
self.yawtimer = math.random() * 2--0
self.followtimer = 0
if self.can_swim then
self.swimtimer = 2 -- ensure we get the first step
-- self.in_water = nil
end
if self.hostile then
self.attacktimer = 0
end
if self.hostile or def.modes.follow then
self.searchtimer = 0
end
if self.can_burn or not def.stats.can_swim or self.has_falldamage then
self.env_damage = true
self.envtimer = 0
end
-- Other things
if staticdata then
local tab = core.deserialize(staticdata)
if tab and type(tab) == "table" then
for s,w in pairs(tab) do
self[tostring(s)] = w
end
end
end
-- check we got a valid mode
if not new_def.modes[self.mode] or (new_def.modes[self.mode].chance or 0) <= 0 then
self.mode = "idle"
end
if not self.can_fly then
if not self.in_water then
self.object:setacceleration({x = 0, y = -15, z = 0})
end
end
-- check if falling and set velocity only 0 when not falling
if self.fall_dist == 0 then
self.object:setvelocity(nullVec)
end
self.object:set_hp(self.hp)
if not core.setting_getbool("enable_damage") then
self.hostile = false
end
-- immortal is needed to disable clientside smokepuff shit
self.object:set_armor_groups({fleshy = 100, immortal = 1})
-- call custom on_activate if defined
if def.on_activate then
def.on_activate(self, staticdata)
end
end
new_def.on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
if def.on_punch and def.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir) == true then
return
end
creatures.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
end
new_def.on_rightclick = function(self, clicker)
if def.on_rightclick and def.on_rightclick(self, clicker) == true then
return
end
creatures.on_rightclick(self, clicker)
end
new_def.on_step = function(self, dtime)
if def.on_step and def.on_step(self, dtime) == true then
return
end
creatures.on_step(self, dtime)
end
return new_def
end
function creatures.register_mob(def) -- returns true if sucessfull
if not def or not def.name then
throw_error("Can't register mob. No name or Definition given.")
return false
end
local mob_def = translate_def(def)
core.register_entity(":" .. def.name, mob_def)
-- register spawn
if def.spawning and not (def.stats.hostile and not allow_hostile) then
local spawn_def = def.spawning
spawn_def.mob_name = def.name
spawn_def.mob_size = def.model.collisionbox
if creatures.register_spawn(spawn_def) ~= true then
throw_error("Couldn't register spawning for '" .. def.name .. "'")
end
if spawn_def.spawn_egg then
local egg_def = def.spawning.spawn_egg
egg_def.mob_name = def.name
egg_def.box = def.model.collisionbox
creatures.register_egg(egg_def)
end
if spawn_def.spawner then
local spawner_def = def.spawning.spawner
spawner_def.mob_name = def.name
spawner_def.range = spawner_def.range or 4
spawner_def.number = spawner_def.number or 6
spawner_def.model = def.model
creatures.register_spawner(spawner_def)
end
end
return true
end
local function inRange(min_max, value)
if not value or not min_max or not min_max.min or not min_max.max then
return false
end
if (value >= min_max.min and value <= min_max.max) then
return true
end
return false
end
local function checkSpace(pos, height)
for i = 0, height do
local n = core.get_node_or_nil({x = pos.x, y = pos.y + i, z = pos.z})
if not n or n.name ~= "air" then
return false
end
end
return true
end
local time_taker = 0
local function step(tick)
core.after(tick, step, tick)
time_taker = time_taker + tick
end
step(0.5)
local function stopABMFlood()
if time_taker == 0 then
return true
end
time_taker = 0
end
local function groupSpawn(pos, mob, group, nodes, range, max_loops)
local cnt = 0
local cnt2 = 0
local nodes = core.find_nodes_in_area({x = pos.x - range, y = pos.y - range, z = pos.z - range},
{x = pos.x + range, y = pos.y, z = pos.z + range}, nodes)
local number = #nodes - 1
if max_loops and type(max_loops) == "number" then
number = max_loops
end
while cnt < group and cnt2 < number do
cnt2 = cnt2 + 1
local p = nodes[math.random(1, number)]
p.y = p.y + 1
if checkSpace(p, mob.size) == true then
cnt = cnt + 1
core.add_entity(p, mob.name)
end
end
if cnt < group then
return false
end
end
function creatures.register_spawn(spawn_def)
if not spawn_def or not spawn_def.abm_nodes then
throw_error("No valid definition for given.")
return false
end
if not spawn_def.abm_nodes.neighbors then
spawn_def.abm_nodes.neighbors = {}
end
table.insert(spawn_def.abm_nodes.neighbors, "air")
core.register_abm({
nodenames = spawn_def.abm_nodes.spawn_on,
neighbors = spawn_def.abm_nodes.neighbors,
interval = spawn_def.abm_interval or 44,
chance = spawn_def.abm_chance or 7000,
catch_up = false,
action = function(pos, node, active_object_count, active_object_count_wider)
-- prevent abm-"feature"
if stopABMFlood() == true then
return
end
-- time check
local tod = core.get_timeofday() * 24000
if spawn_def.time_range then
local wanted_res = false
local range = table.copy(spawn_def.time_range)
if range.min > range.max and range.min <= tod then
wanted_res = true
end
if inRange(range, tod) == wanted_res then
return
end
end
-- position check
if spawn_def.height_limit and not inRange(spawn_def.height_limit, pos.y) then
return
end
-- light check
pos.y = pos.y + 1
local llvl = core.get_node_light(pos)
if spawn_def.light and not inRange(spawn_def.light, llvl) then
return
end
-- creature count check
local max
if active_object_count_wider > (spawn_def.max_number or 1) then
local mates_num = #creatures.findTarget(nil, pos, 16, "mate", spawn_def.mob_name, true)
if (mates_num or 0) >= spawn_def.max_number then
return
else
max = spawn_def.max_number - mates_num
end
end
-- ok everything seems fine, spawn creature
local height_min = (spawn_def.mob_size[5] or 2) - (spawn_def.mob_size[2] or 0)
height_min = math.ceil(height_min)
local number = 0
if type(spawn_def.number) == "table" then
number = math.random(spawn_def.number.min, spawn_def.number.max)
else
number = spawn_def.number or 1
end
if max and number > max then
number = max
end
if number > 1 then
groupSpawn(pos, {name = spawn_def.mob_name, size = height_min}, number, spawn_def.abm_nodes.spawn_on, 5)
else
-- space check
if not checkSpace(pos, height_min) then
return
end
core.add_entity(pos, spawn_def.mob_name)
end
end,
})
return true
end
local function eggSpawn(itemstack, placer, pointed_thing, egg_def)
if pointed_thing.type == "node" then
local pos = pointed_thing.above
pos.y = pos.y + 0.5
local height = (egg_def.box[5] or 2) - (egg_def.box[2] or 0)
if checkSpace(pos, height) == true then
core.add_entity(pos, egg_def.mob_name)
if core.setting_getbool("creative_mode") ~= true then
itemstack:take_item()
end
end
return itemstack
end
end
function creatures.register_egg(egg_def)
if not egg_def or not egg_def.mob_name or not egg_def.box then
throw_error("Can't register Spawn-Egg. Not enough parameters given.")
return false
end
core.register_craftitem(":" .. egg_def.mob_name .. "_spawn_egg", {
description = egg_def.description or egg_def.mob_name .. " spawn egg",
inventory_image = egg_def.texture or "creatures_spawn_egg.png",
liquids_pointable = false,
on_place = function(itemstack, placer, pointed_thing)
return eggSpawn(itemstack, placer, pointed_thing, egg_def)
end,
})
return true
end
local function makeSpawnerEntiy(mob_name, model)
core.register_entity(":" .. mob_name .. "_spawner_dummy", {
hp_max = 1,
physical = false,
collide_with_objects = false,
collisionbox = nullVec,
visual = "mesh",
visual_size = {x = 0.42, y = 0.42},
mesh = model.mesh,
textures = model.textures,
makes_footstep_sound = false,
automatic_rotate = math.pi * -2.9,
mob_name = "_" .. mob_name .. "_dummy",
on_activate = function(self)
self.timer = 0
self.object:setvelocity(nullVec)
self.object:setacceleration(nullVec)
self.object:set_armor_groups({immortal = 1})
--self.object:set_bone_position("Root", nullVec, {x=45,y=0,z=0})
end,
on_step = function(self, dtime)
self.timer = self.timer + dtime
if self.timer > 30 then
self.timer = 0
local n = core.get_node_or_nil(self.object:getpos())
if n and n.name and n.name ~= mob_name .. "_spawner" then
self.object:remove()
end
end
end
})
end
local function spawnerSpawn(pos, spawner_def)
local mates = creatures.findTarget(nil, pos, spawner_def.range, "mate", spawner_def.mob_name, true) or {}
if #mates >= spawner_def.number then
return false
end
local number_max = spawner_def.number - #mates
local rh = math.floor(spawner_def.range/2)
local area = {
min = {x = pos.x - rh, y=pos.y - rh, z = pos.z - rh},
max = {x = pos.x + rh, y=pos.y + rh - spawner_def.height - 1, z = pos.z + rh}
}
local height = area.max.y - area.min.y
local cnt = 0
for i = 0, height do
if cnt >= number_max then
break
end
local p = {x = math.random(area.min.x, area.max.x), y = area.min.y + i, z = math.random(area.min.z, area.max.z)}
local n = core.get_node_or_nil(p)
if n and n.name then
local walkable = core.registered_nodes[n.name].walkable or false
p.y = p.y + 1
if walkable and checkSpace(p, spawner_def.height) == true then
local llvl = core.get_node_light(p)
if not spawner_def.light or (spawner_def.light and inRange(spawner_def.light, llvl)) then
cnt = cnt + 1
core.add_entity(p, spawner_def.mob_name)
end
end
end
end
end
local spawner_timers = {}
function creatures.register_spawner(spawner_def)
if not spawner_def or not spawner_def.mob_name or not spawner_def.model then
throw_error("Can't register Spawn-Egg. Not enough parameters given.")
return false
end
makeSpawnerEntiy(spawner_def.mob_name, spawner_def.model)
core.register_node(":" .. spawner_def.mob_name .. "_spawner", {
description = spawner_def.description or spawner_def.mob_name .. " spawner",
paramtype = "light",
tiles = {"creatures_spawner.png"},
is_ground_content = true,
drawtype = "glasslike",
groups = {cracky = 1, level = 1},
drop = "",
on_construct = function(pos)
pos.y = pos.y - 0.3
core.add_entity(pos, spawner_def.mob_name .. "_spawner_dummy")
end,
on_destruct = function(pos)
for _,obj in ipairs(core.get_objects_inside_radius(pos, 1)) do
local entity = obj:get_luaentity()
if obj and entity and entity.mob_name == "_" .. spawner_def.mob_name .. "_dummy" then
obj:remove()
end
end
end
})
local box = spawner_def.model.collisionbox
local height = (box[5] or 2) - (box[2] or 0)
spawner_def.height = height
if spawner_def.player_range and type(spawner_def.player_range) == "number" then
core.register_abm({
nodenames = {spawner_def.mob_name .. "_spawner"},
interval = 2,
chance = 1,
catch_up = false,
action = function(pos)
local id = core.pos_to_string(pos)
if not spawner_timers[id] then
spawner_timers[id] = os.time()
end
local time_from_last_call = os.time() - spawner_timers[id]
local mobs,player_near = creatures.findTarget(nil, pos, spawner_def.player_range, "player", nil, true, true)
if player_near == true and time_from_last_call > 10 and (math.random(1, 5) == 1 or (time_from_last_call ) > 27) then
spawner_timers[id] = os.time()
spawnerSpawn(pos, spawner_def)
end
end
})
else
core.register_abm({
nodenames = {spawner_def.mob_name .. "_spawner"},
interval = 10,
chance = 3,
action = function(pos)
spawnerSpawn(pos, spawner_def)
end
})
end
return true
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 686 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

View File

@ -1,20 +0,0 @@
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no
event will the authors be held liable for any damages arising from the use of
this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to the
following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation is required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -1,31 +0,0 @@
Chicken for Creatures MOB-Engine
================================
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
Version: 2.2
Adds chicken to Minetest (requires Creatures MOB-Engine).
Chicken spawn on dirt and grass blocks, have 5 HP and are friendly. When killed or dying
they drop meat, which can be eaten or cooked and probably some feathers. Also they drop
randomly eggs, which can be thrown to spawn new chicken or fried and eaten.
License:
~~~~~~~~
Code:
(c) Copyright 2015-2016 BlockMen; modified zlib-License
see "LICENSE.txt" for details.
Media(textures and meshes/models):
Gamit(WTFPL):
creatures_egg.png
everything else:
(c) Copyright (2014-2016) BlockMen; CC-BY-SA 3.0
Sounds:
- creatures_chicken*.ogg, dobroide(https://freesound.org/people/dobroide) CC BY 3.0
Github:
~~~~~~~
https://github.com/BlockMen/cme/chicken

View File

@ -1,20 +0,0 @@
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no
event will the authors be held liable for any damages arising from the use of
this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to the
following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation is required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -1,31 +0,0 @@
Chicken for Creatures MOB-Engine
================================
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
Version: 2.2
Adds chicken to Minetest (requires Creatures MOB-Engine).
Chicken spawn on dirt and grass blocks, have 5 HP and are friendly. When killed or dying
they drop meat, which can be eaten or cooked and probably some feathers. Also they drop
randomly eggs, which can be thrown to spawn new chicken or fried and eaten.
License:
~~~~~~~~
Code:
(c) Copyright 2015-2016 BlockMen; modified zlib-License
see "LICENSE.txt" for details.
Media(textures and meshes/models):
Gamit(WTFPL):
creatures_egg.png
everything else:
(c) Copyright (2014-2016) BlockMen; CC-BY-SA 3.0
Sounds:
- creatures_chicken*.ogg, dobroide(https://freesound.org/people/dobroide) CC BY 3.0
Github:
~~~~~~~
https://github.com/BlockMen/cme/chicken

View File

@ -1,20 +0,0 @@
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
This software is provided 'as-is', without any express or implied warranty. In no
event will the authors be held liable for any damages arising from the use of
this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to the
following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation is required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@ -1,31 +0,0 @@
Chicken for Creatures MOB-Engine
================================
Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
Version: 2.2
Adds chicken to Minetest (requires Creatures MOB-Engine).
Chicken spawn on dirt and grass blocks, have 5 HP and are friendly. When killed or dying
they drop meat, which can be eaten or cooked and probably some feathers. Also they drop
randomly eggs, which can be thrown to spawn new chicken or fried and eaten.
License:
~~~~~~~~
Code:
(c) Copyright 2015-2016 BlockMen; modified zlib-License
see "LICENSE.txt" for details.
Media(textures and meshes/models):
Gamit(WTFPL):
creatures_egg.png
everything else:
(c) Copyright (2014-2016) BlockMen; CC-BY-SA 3.0
Sounds:
- creatures_chicken*.ogg, dobroide(https://freesound.org/people/dobroide) CC BY 3.0
Github:
~~~~~~~
https://github.com/BlockMen/cme/chicken

View File

@ -1,7 +1,7 @@
--= torchick for poketesr (cme) =--
--engine: Copyright (c) 2015-2016 BlockMen <blockmen2015@gmail.com>
--poketest: Copyright (c) 2017 MBB <MBB@webproxy.li>
--NODEBOX OF TIS POKEMON BY <DOOMED>
--poketest: Copyright (c) 2017 MBB <mbb@webproxy.li>
--NODEBOX OF THIS POKEMON BY <DOOMED>
-- init.lua
--
--POKETEST USES BLOCKMEN´S CREATURES MOB ENGINE
@ -28,79 +28,77 @@
local def = {
-- general
name = "poketest:torchick",
stats = {
hp = 5,
lifetime = 300, -- 5 Minutes
can_jump = 1,
can_swim = true,
can_burn = true,
can_panic = true,
has_kockback = true,
sneaky = true,
},
-- general
name = "poketest:torchick",
stats = {
hp = 5,
lifetime = 300, -- 5 Minutes
can_jump = 1,
can_swim = true,
can_burn = true,
can_panic = true,
has_kockback = true,
sneaky = true,
},
modes = {
idle = {chance = 0.25, duration = 5, update_yaw = 3},
idle2 = {chance = 0.69, duration = 0.8},
pick = {chance = 0.2, duration = 2},
walk = {chance = 0.2, duration = 5.5, moving_speed = 0.7, update_yaw = 2},
panic = {moving_speed = 2.1},
lay_egg = {chance = 0.01, duration = 1},
},
modes = {
idle = {chance = 0.25, duration = 5, update_yaw = 3},
idle2 = {chance = 0.69, duration = 0.8},
pick = {chance = 0.2, duration = 2},
walk = {chance = 0.2, duration = 5.5, moving_speed = 0.7, update_yaw = 2},
panic = {moving_speed = 2.1},
lay_egg = {chance = 0.01, duration = 1},
},
model = {
mesh = "poketest_torchick.b3d",
textures = {"poketest_torchick.png"},
collisionbox = {-0.25, -0.01, -0.3, 0.25, 0.45, 0.3},
rotation = -90,
model = {
mesh = "poketest_torchick.b3d",
textures = {"poketest_torchick.png"},
collisionbox = {-0.25, -0.01, -0.3, 0.25, 0.45, 0.3},
rotation = -90,
collide_with_objects = false,
animations = {
idle = {start = 0, stop = 1, speed = 10},
idle2 = {start = 40, stop = 50, speed = 50},
pick = {start = 88, stop = 134, speed = 50},
walk = {start = 4, stop = 36, speed = 50},
-- special modes
swim = {start = 51, stop = 87, speed = 40},
panic = {start = 51, stop = 87, speed = 55},
death = {start = 135, stop = 160, speed = 28, loop = false, duration = 2.12},
},
},
collide_with_objects = false,
animations = {
idle = {start = 0, stop = 1, speed = 10},
idle2 = {start = 40, stop = 50, speed = 50},
pick = {start = 88, stop = 134, speed = 50},
walk = {start = 4, stop = 36, speed = 50},
-- special modes
swim = {start = 51, stop = 87, speed = 40},
panic = {start = 51, stop = 87, speed = 55},
death = {start = 135, stop = 160, speed = 28, loop = false, duration = 2.12},
},
},
sounds = {
on_damage = {name = "poketest_torchick_hit", gain = 0.5, distance = 10},
on_death = {name = "poketest_torchick_hit", gain = 0.5, distance = 10},
swim = {name = "creatures_splash", gain = 1.0, distance = 10},
random = {
idle = {name = "poketest_torchick", gain = 0.9, distance = 12, time_min = 8, time_max = 50},
},
},
sounds = {
on_damage = {name = "poketest_torchick_hit", gain = 0.5, distance = 10},
on_death = {name = "poketest_torchick_hit", gain = 0.5, distance = 10},
swim = {name = "creatures_splash", gain = 1.0, distance = 10},
random = {
idle = {name = "poketest_torchick", gain = 0.9, distance = 12, time_min = 8, time_max = 50},
},
},
spawning = {
abm_nodes = {
spawn_on = {"default:dirt_with_grass", "default:dirt"},
},
abm_interval = 55,
abm_chance = 7800,
max_number = 1,
number = 1,
light = {min = 8, max = 15},
height_limit = {min = 0, max = 150},
spawning = {
abm_nodes = {
spawn_on = {"default:dirt_with_grass", "default:dirt"},
},
abm_interval = 55,
abm_chance = 7800,
max_number = 1,
number = 1,
light = {min = 8, max = 15},
height_limit = {min = 0, max = 150},
spawn_egg = {
description = "torchick Spawn-Egg",
texture = "poketest_egg_torchick.png",
},
},
spawn_egg = {
description = "torchick Spawn-Egg",
texture = "poketest_egg_torchick.png",
},
},
drops = {
{"default:meat"},
drops = {
{"default:meat"},
},
},
}
creatures.register_mob(def)