This commit is contained in:
WilLiam12 2021-07-21 13:57:10 -03:00
parent 6d00b76da5
commit 7462c9a95c
892 changed files with 25573 additions and 0 deletions

4
petz/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
## Generic ignorable patterns and files
*.obj
*.blend1
user.conf

31
petz/.luacheckrc Normal file
View File

@ -0,0 +1,31 @@
unused_args = false
allow_defined_top = true
max_line_length = false
globals = {
"minetest",
"mobkit",
"mokapi",
"petz",
"stairs",
"farming",
"player_api",
"hunger_ng",
"dye",
"armor",
"playerphysics",
"player_monoids",
"awards"
}
read_globals = {
string = {fields = {"split"}},
table = {fields = {"copy", "getn"}},
-- Builtin
"vector", "ItemStack",
"dump", "DIR_DELIM", "VoxelArea", "Settings",
-- MTG
"default", "sfinv", "creative",
}

5
petz/LICENSE.md Normal file
View File

@ -0,0 +1,5 @@
# Licenses
- Source code: GPLv3.
- Textures: CC BY-SA 4.0
- Sounds: They have different licenses, see the 'sounds/LICENSE.MD' file.

9
petz/README.md Normal file
View File

@ -0,0 +1,9 @@
# Petz [petz]
Cute kawaii mobs for Minetest.
## Licenses
- Code: GPL v3.0
- Textures: CC BY-SA 4.0
- Sounds: They have different licenses, see the 'sounds/LICENSE.MD' file.

19
petz/bale/init.lua Normal file
View File

@ -0,0 +1,19 @@
S = minetest.get_translator(minetest.get_current_modname())
minetest.register_node("bale:bale", {
description = S("Bale"),
tiles = {"bale_bale.png"},
is_ground_content = false,
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3,
flammable = 3, feeder = 1},
sounds = default.node_sound_defaults(),
})
minetest.register_craft({
output = 'bale:bale',
recipe = {
{'farming:wheat', 'farming:wheat', 'farming:wheat'},
{'farming:wheat', 'farming:wheat', 'farming:wheat'},
{'farming:wheat', 'farming:wheat', 'farming:wheat'},
}
})

View File

@ -0,0 +1,2 @@
# textdomain: bale
Bale=Fardo de feno

View File

@ -0,0 +1,2 @@
# textdomain: bale
Bale=Heuballen

View File

@ -0,0 +1,2 @@
# textdomain: bale
Bale=Paca de heno

View File

@ -0,0 +1,2 @@
# textdomain: bale
Bale=Botte de foin

View File

@ -0,0 +1,2 @@
# textdomain: bale
Bale=тюк сена

3
petz/bale/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = bale
description = A bale of hay (wheat)
depends = farming

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

5
petz/modpack.conf Normal file
View File

@ -0,0 +1,5 @@
description = Very cute mascots: Kittens, puppies, duckies, lambs... Take care of them!
author = runs
title = Petz
release = 8560
name = petz

0
petz/modpack.txt Normal file
View File

113
petz/mokapi/README.md Normal file
View File

@ -0,0 +1,113 @@
# Drop Functions
## mokapi.drop_item(self, item, num)
Mob drops only one item.
## mokapi.drop_items(self, killed_by_player)
Mob drops a table list of items defined in the entity.
Example of the 'drops' definition:
```
drops = {
{name = "petz:mini_lamb_chop", chance = 1, min = 1, max = 1,},
{name = "petz:bone", chance = 5, min = 1, max = 1,},
},
```
## mokapi.node_drop_items(pos)
Node drops the "drops" list saved in the node metadata.
# Sound Functions
## mokapi.make_misc_sound(self, chance, max_hear_distance)
Make a random sound from the "misc" sound definition.
The misc definition can be a single sound or a table of sounds.
Example of the 'misc' definition:
```
sounds = {
misc = {"petz_kitty_meow", "petz_kitty_meow2", "petz_kitty_meow3"},
},
```
## mokapi.make_sound(dest_type, dest, soundfile, max_hear_distance)
Make a sound on dest accordingly dest_type.
dest_type can be "object, "player" or "pos".
# Replace Function
## mokapi.replace(self, sound_name, max_hear_distance)
Replace a node to another. Useful for eating grass.
'sound_name' & 'max_hear_distance' are optionals.
Example of the 'replace_what' definition:
```
replace_rate = 10,
replace_offset = 0,
replace_what = {
{"group:grass", "air", -1},
{"default:dirt_with_grass", "default:dirt", -2}
},
```
3 parameters for 'replace_what': replace_what, replace_with and y_offset
# Feed & Tame Functions
## function mokapi.feed(self, clicker, feed_rate, msg_full_health, sound_type)
It returns true if fed.
It checks against a string, a stringlist separated by commas or a table of 'self.follow' items or groups.
```
self.follow = "farming:wheat"
self.follow = "group:food_meat_raw, mobs:raw_chicken"
self.follow = {"group:food_meat_raw", "mobs:raw_chicken"}
```
'feed_rate' (from 0.0 to 1.0) is the percentage to heal referenced to self.max_hp
msg_full_health is optional
sound_type is the self.sound type
## function mokapi.tame(self, feed_count, owner_name, msg_tamed, limit)
It returns true if tamed.
'feed_count' is the amount of food to get the mob tamed.
'limit' is an optional table with the following data:
1. max = The limit of the tamed mobs by player
2. count = The current number of tamed mobs of the specific player that wants to tame
3. msg = Message when the limit of tamed mobs is reached
if 'max > count + 1' then the taming process is aborted.
## function mokapi.set_owner(self, owner_name)
Put 'self.tamed' to true and the 'self.owner' name.
## function mokapi.remove_owner(self)
Put 'self.tamed' to false and the 'self.owner' to nil.
## function mokapi.set_health(self, rate)
'rate' (from 0.0 to 1.0) is the percentage of self.max_hp
rate can be positive or negative
# Helper Functions
## function mokapi.remove_mob(self)
It clears the mob HQ and LQ behaviours and then remove it from the world.
# Commands
## clear_mobs modname
It clears all the mobkit non-tamed mobs in the closest range of the player.
Modname is the mod of the mobs to clear.
# Server
## function mokapi.cron_clear(cron_time, modname)
It creates a cron task to clearing all the 'modname' non-tamed mobs in the closest range of all the server's players (or game) from time to time.
If cron_time <= 0 then the cron task does not run.

View File

@ -0,0 +1,13 @@
function mokapi.clear_mobs(pos, modname)
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 100)) do
local ent_name = obj:get_entity_name()
if not(obj:is_player()) and minetest.registered_entities[ent_name] then
local colon_pos = string.find(ent_name, ':')
local ent_modname = string.sub(ent_name, 1, colon_pos-1)
local ent = obj:get_luaentity()
if ent_modname == modname and ent.type and not(ent.tamed) then
mokapi.remove_mob(ent)
end
end
end
end

View File

@ -0,0 +1,17 @@
minetest.register_chatcommand("clear_mobs", {
description = "Clear all non-tamed mobs",
privs = {
server = true,
},
func = function(name, param)
local modname = string.match(param, "([%a%d_-]+)")
if not modname then
return true, "Error: You have to specifiy a namespace (mod name)"
end
local player_pos = minetest.get_player_by_name(name):get_pos()
if not player_pos then
return
end
mokapi.clear_mobs(player_pos, modname)
end,
})

View File

@ -0,0 +1,4 @@
mokapi.consts = {}
mokapi.consts.DEFAULT_MAX_HEAR_DISTANCE = 5
mokapi.consts.DEFAULT_FEED_RATE = 0.3
mokapi.consts.DEFAULT_FEED_COUNT = 5

View File

@ -0,0 +1,15 @@
function mokapi.cron_clear(cron_time, modname)
if cron_time > 0 then
minetest.after(cron_time, function()
mokapi.cron_clear_mobs(cron_time, modname)
end, cron_time, modname)
end
end
function mokapi.cron_clear_mobs(cron_time, modname)
for _, player in ipairs(minetest.get_connected_players()) do
local player_pos = player:get_pos()
mokapi.clear_mobs(player_pos, modname)
end
mokapi.cron_clear(cron_time, modname)
end

View File

@ -0,0 +1,84 @@
--
--Helper funtions
--
function mokapi.drop_velocity(obj)
obj:set_velocity({
x = math.random(-10, 10) / 9,
y = 6,
z = math.random(-10, 10) / 9,
})
end
function mokapi.drop_object(obj)
if obj and obj:get_luaentity() then
mokapi.drop_velocity(obj)
elseif obj then
obj:remove() -- item does not exist
end
end
--
--Functions
--
function mokapi.drop_item(self, item, num)
if not item then
return
end
if not num then
num = 1
end
local pos
if type(self) == 'table' then --entity
pos = self.object:get_pos()
else --player
pos = self:get_pos()
end
local obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
mokapi.drop_object(obj)
end
function mokapi.drop_items(self, killed_by_player)
if not self.drops or #self.drops == 0 then -- check for nil or no drops
return
end
if self.child then -- no drops for child mobs
return
end
local obj, item, num
local pos = self.object:get_pos()
for n = 1, #self.drops do
if math.random(1, self.drops[n].chance) == 1 then
num = math.random(self.drops[n].min or 0, self.drops[n].max or 1)
item = self.drops[n].name
if killed_by_player then -- only drop rare items (drops.min=0) if killed by player
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
elseif self.drops[n].min ~= 0 then
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
end
mokapi.drop_object(obj)
end
end
self.drops = {}
end
function mokapi.node_drop_items(pos)
local meta = minetest.get_meta(pos)
if not meta then
return
end
local drops= minetest.deserialize(meta:get_string("drops"))
if not drops or #drops == 0 then -- check for nil or no drops
return
end
local obj, item, num
for n = 1, #drops do
if math.random(1, drops[n].chance) == 1 then
num = math.random(drops[n].min or 0, drops[n].max or 1)
item = drops[n].name
if drops[n].min ~= 0 then
obj = minetest.add_item(pos, ItemStack(item .. " " .. num))
end
mokapi.drop_object(obj)
end
end
end

View File

@ -0,0 +1,76 @@
function mokapi.feed(self, clicker, feed_rate, msg_full_health, sound_type)
local fed = false
local wielded_item = clicker:get_wielded_item()
local wielded_item_name = wielded_item:get_name()
if mokapi.item_in_itemlist(wielded_item_name, self.follow) then -- Can eat/tame with item in hand
fed = true
local creative_mode = minetest.settings:get_bool("creative_mode")
if creative_mode == false then -- if not in creative, take item
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
end
--Feed-->
mokapi.set_health(self, feed_rate or mokapi.consts.DEFAULT_FEED_RATE)
if self.hp >= self.max_hp then
self.hp = self.max_hp
if msg_full_health then
minetest.chat_send_player(clicker:get_player_name(), msg_full_health)
end
end
self.food_count = mobkit.remember(self, "food_count", self.food_count + 1) --increase the food count
if sound_type then
mobkit.make_sound(self, sound_type)
end
end
return fed
end
function mokapi.tame(self, feed_count, owner_name, msg_tamed, limit)
local tamed = false
if self.food_count >= (feed_count or mokapi.consts.DEFAULT_FEED_COUNT) then
self.food_count = mobkit.remember(self, "food_count", 0) --reset
if self.tamed == false then --if not tamed
local limit_reached = false
if limit and (limit.max >= 0) then
--minetest.chat_send_player(owner_name, "limit.max="..tostring(limit.max)..", limit.count="..tostring(limit.count))
if (limit.count +1) > limit.max then
minetest.chat_send_player(owner_name, limit.msg)
limit_reached = true
end
end
if not limit_reached then
tamed = true
mokapi.set_owner(self, owner_name)
if msg_tamed then
minetest.chat_send_player(owner_name, msg_tamed)
end
mobkit.clear_queue_high(self) -- clear behaviour (i.e. it was running away)
end
end
end
return tamed
end
function mokapi.set_owner(self, owner_name)
self.tamed = mobkit.remember(self, "tamed", true)
self.owner = mobkit.remember(self, "owner", owner_name)
end
function mokapi.remove_owner(self)
self.tamed = mobkit.remember(self, "tamed", false)
self.owner = mobkit.remember(self, "owner", nil)
end
--Calculate heal/hurt hunger
function mokapi.set_health(self, rate)
if rate > 1.0 then
rate = 1.0
end
local hp_amount = math.abs(self.max_hp * rate)
if rate >= 0 then
mobkit.heal(self, hp_amount)
else
mobkit.hurt(self, hp_amount)
end
end

View File

@ -0,0 +1,40 @@
function mokapi.item_in_itemlist(item_name, itemlist)
local match = false
local table = false
if type(itemlist) == "table" then
table = true
end
if item_name and itemlist then
local items
if not table then
items = string.split(itemlist, ',')
else
items = itemlist
end
for i = 1, #items do --loop thru all items
--minetest.chat_send_player("singleplayer", "itemlist item="..items[i])
--minetest.chat_send_player("singleplayer", "item name="..item_name)
local item = petz.str_remove_spaces(items[i]) --remove spaces
if string.sub(item, 1, 5) == "group" then
local item_group = minetest.get_item_group(item_name, string.sub(item, 7))
if item_group > 0 then
match = true
break
end
else
if item == item_name then --if node name matches
match = true
break
end
end
end
return match
end
end
function mokapi.remove_mob(self)
--IMPORTANT: Firstly: Delete Behaviours
mobkit.clear_queue_high(self)
mobkit.clear_queue_low(self)
self.object:remove()
end

View File

@ -0,0 +1,43 @@
function mokapi.delimit_number(number, range)
if not tonumber(number) then
return nil
end
if number < range.min then
number = range.min
elseif number > range.max then
number = range.max
end
return number
end
function mokapi.round(x)
return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
end
--Trigonometric Functions
--converts yaw to degrees
function mokapi.degrees(yaw)
return(yaw * 180.0 / math.pi)
end
function mokapi.degrees_to_radians(degrees)
return(degrees/180.0*math.pi)
end
--converts yaw to degrees
function mokapi.yaw_to_degrees(yaw)
return(yaw*180.0/math.pi)
end
--rounds it up to an integer
function mokapi.degree_round(degree)
return(degree + 0.5 - (degree + 0.5) % 1)
end
--turns radians into degrees - not redundant
--doesn't add math.pi
function mokapi.radians_to_degrees(radians)
return(radians*180.0/math.pi)
end

View File

@ -0,0 +1,31 @@
--
--Replace Engine
--
function mokapi.replace(self, sound_name, max_hear_distance)
if not self.replace_rate or not self.replace_what or self.child == true or self.object:get_velocity().y ~= 0 or math.random(1, self.replace_rate) > 1 then
return false
end
local pos = self.object:get_pos()
local what, with, y_offset
if type(self.replace_what[1]) == "table" then
local num = math.random(#self.replace_what)
what = self.replace_what[num][1] or ""
with = self.replace_what[num][2] or ""
y_offset = self.replace_what[num][3] or 0
else
what = self.replace_what
with = self.replace_with or ""
y_offset = self.replace_offset or 0
end
pos.y = pos.y + y_offset
if #minetest.find_nodes_in_area(pos, pos, what) > 0 then
minetest.set_node(pos, {name = with})
if sound_name then
mokapi.make_sound("object", self.object, sound_name, max_hear_distance or mokapi.consts.DEFAULT_MAX_HEAR_DISTANCE)
end
return true
else
return false
end
end

View File

@ -0,0 +1,33 @@
--
--Sound System
--
function mokapi.make_misc_sound(self, chance, max_hear_distance)
if self.muted == true then
return
end
local random_number = math.random(1, chance)
if random_number == 1 then
if self.sounds and self.sounds['misc'] then
local misc_sound
if (type(self.sounds['misc']) == "table") then
misc_sound = self.sounds['misc'][math.random(1, #self.sounds['misc'])]
else
misc_sound = self.sounds['misc']
end
mokapi.make_sound("object", self.object, misc_sound, max_hear_distance or mokapi.consts.DEFAULT_MAX_HEAR_DISTANCE)
end
end
end
function mokapi.make_sound(dest_type, dest, soundfile, max_hear_distance)
if dest_type == "object" then
minetest.sound_play(soundfile, {object = dest, gain = 0.5, max_hear_distance = max_hear_distance or mokapi.consts.DEFAULT_MAX_HEAR_DISTANCE,})
elseif dest_type == "player" then
local player_name = dest:get_player_name()
--minetest.chat_send_player("singleplayer", player_name..tostring(max_hear_distance))
minetest.sound_play(soundfile, {to_player = player_name, gain = 0.5, max_hear_distance = max_hear_distance or mokapi.consts.DEFAULT_MAX_HEAR_DISTANCE,})
elseif dest_type == "pos" then
minetest.sound_play(soundfile, {pos = dest, gain = 0.5, max_hear_distance = max_hear_distance or mokapi.consts.DEFAULT_MAX_HEAR_DISTANCE,})
end
end

14
petz/mokapi/init.lua Normal file
View File

@ -0,0 +1,14 @@
mokapi = {} --the global variable
local modname = "mokapi" --the modname
local modpath = minetest.get_modpath(modname) --the modpath
--load the apis:
assert(loadfile(modpath.."/api/api_consts.lua"))()
assert(loadfile(modpath.."/api/api_cron.lua"))()
assert(loadfile(modpath.."/api/api_clear_mobs.lua"))()
assert(loadfile(modpath.."/api/api_drops.lua"))()
assert(loadfile(modpath.."/api/api_sound.lua"))()
assert(loadfile(modpath.."/api/api_replace.lua"))()
assert(loadfile(modpath.."/api/api_feed_tame.lua"))()
assert(loadfile(modpath.."/api/api_helper_functions.lua"))()
assert(loadfile(modpath.."/api/api_commands.lua"))()
assert(loadfile(modpath.."/api/api_math.lua"))()

3
petz/mokapi/mod.conf Normal file
View File

@ -0,0 +1,3 @@
name = mokapi
description = A high level API for mobkit
depends = mobkit

2
petz/petz/CHANGELOG.md Normal file
View File

@ -0,0 +1,2 @@

9
petz/petz/README.md Normal file
View File

@ -0,0 +1,9 @@
# Petz [petz]
Cute kawaii mobs for Minetest.
## Licenses
- Code: GPL v3.0
- Textures: CC BY-SA 4.0
- Sounds: They have different licenses, see the 'sounds/LICENSE.MD' file.

45
petz/petz/api/api.lua Normal file
View File

@ -0,0 +1,45 @@
local modpath, S = ...
assert(loadfile(modpath .. "/api/api_helper_functions.lua"))()
assert(loadfile(modpath .. "/api/api_datetime.lua"))()
assert(loadfile(modpath .. "/api/api_spawn.lua"))()
assert(loadfile(modpath .. "/api/api_orders.lua"))()
assert(loadfile(modpath .. "/api/api_init_prop.lua"))() --Load the init the properties for the entities
assert(loadfile(modpath .. "/api/api_forms.lua"))(S)
assert(loadfile(modpath .. "/api/api_on_rightclick.lua"))(S)
assert(loadfile(modpath .. "/api/api_on_die.lua"))()
assert(loadfile(modpath .. "/api/api_on_punch.lua"))()
assert(loadfile(modpath .. "/api/api_feed_tame.lua"))(S)
assert(loadfile(modpath .. "/api/api_capture.lua"))(S)
assert(loadfile(modpath .. "/api/api_tamagochi.lua"))(S)
assert(loadfile(modpath .. "/api/api_breed.lua"))(S)
assert(loadfile(modpath .. "/api/api_wool_milk.lua"))(S)
assert(loadfile(modpath .. "/api/api_mount.lua"))()
assert(loadfile(modpath .. "/api/api_dreamcatcher.lua"))(S)
assert(loadfile(modpath .. "/api/api_eggs.lua"))()
assert(loadfile(modpath .. "/api/api_squareball.lua"))(S)
assert(loadfile(modpath .. "/api/api_convert.lua"))(S)
assert(loadfile(modpath .. "/api/api_nametag.lua"))()
assert(loadfile(modpath .. "/api/api_dam_beaver.lua"))(modpath)
assert(loadfile(modpath .. "/api/api_particles.lua"))()
assert(loadfile(modpath .. "/api/api_whistle.lua"))(S)
assert(loadfile(modpath .. "/api/api_silk.lua"))(S)
assert(loadfile(modpath .. "/api/api_on_step.lua"))()
assert(loadfile(modpath .. "/api/api_sleep.lua"))()
assert(loadfile(modpath .. "/api/api_env_damage.lua"))()
assert(loadfile(modpath .. "/api/api_bees.lua"))(S)
assert(loadfile(modpath .. "/api/api_throw.lua"))()
assert(loadfile(modpath .. "/api/api_collisionbox.lua"))()
assert(loadfile(modpath .. "/api/api_colorize.lua"))()
assert(loadfile(modpath .. "/api/api_horseshoes.lua"))(S)
assert(loadfile(modpath .. "/api/api_blood.lua"))()
assert(loadfile(modpath .. "/api/api_poop.lua"))()
assert(loadfile(modpath .. "/api/api_brush.lua"))(S)
assert(loadfile(modpath .. "/api/api_bottled.lua"))(modpath, S)
assert(loadfile(modpath .. "/api/api_colors.lua"))()
assert(loadfile(modpath .. "/api/api_sell_buy.lua"))(S)
assert(loadfile(modpath .. "/api/api_lifetime.lua"))()
assert(loadfile(modpath .. "/api/api_back_home.lua"))()
assert(loadfile(modpath .. "/api/api_on_deactivate.lua"))()
assert(loadfile(modpath .. "/api/api_wagon.lua"))()

View File

@ -0,0 +1,40 @@
function petz.back_home(self)
local pos = self.object:get_pos()
local home_pos = self.home_pos
if not home_pos then
return
end
local distance = vector.distance(pos, home_pos)
if distance <= petz.settings["back_home_distance"] then
return
end
local node = minetest.get_node_or_nil(home_pos)
local map_loaded
if not node then
-- Load the map at pos and try again
--minetest.chat_send_all("manip")
minetest.get_voxel_manip():read_from_map(home_pos, home_pos)
node = minetest.get_node(pos)
map_loaded = true
end
if not node then
return
end
if node.name == "air" then
--minetest.chat_send_all("test")
local forceload
if map_loaded then
forceload = minetest.forceload_block(home_pos)
--minetest.chat_send_all("FORCELOAD")
if not forceload then
--minetest.chat_send_all("NO FORCELOAD")
return
end
end
--minetest.chat_send_all("test2")
self.object:set_pos(home_pos)
if map_loaded then
minetest.forceload_free_block(pos)
end
end
end

View File

@ -0,0 +1,62 @@
local S = ...
petz.set_infotext_behive = function(meta, honey_count, bee_count)
local total_bees = meta:get_int("total_bees") or petz.settings.max_bees_behive
meta:set_string("infotext", S("Honey")..": "..tostring(honey_count) .." | "..S("Bees Inside")..": "..tostring(bee_count).." | "..S("Total Bees")..": "..tostring(total_bees))
end
petz.decrease_total_bee_count = function(pos)
local meta = minetest.get_meta(pos)
local total_bees = meta:get_int("total_bees") or petz.settings.max_bees_behive
total_bees = total_bees - 1
meta:set_int("total_bees", total_bees)
end
petz.behive_exists = function(self)
local behive_exists
if self.behive then
local node = minetest.get_node_or_nil(self.behive)
if node and node.name == "petz:beehive" then
behive_exists = true
else
behive_exists = false
end
else
behive_exists = false
end
if behive_exists then
return true
else
self.behive = nil
return false
end
end
petz.get_behive_stats = function(pos)
if not(pos) then
return
end
local meta = minetest.get_meta(pos)
local honey_count = meta:get_int("honey_count") or 0
local bee_count = meta:get_int("bee_count") or 0
return meta, honey_count, bee_count
end
petz.spawn_bee_pos = function(pos) --Check a pos close to a behive to spawn a bee
local pos_1 = {
x = pos.x - 1,
y = pos.y - 1,
z = pos.z - 1,
}
local pos_2 = {
x = pos.x + 1,
y = pos.y + 1,
z = pos.z + 1,
}
local spawn_pos_list = minetest.find_nodes_in_area(pos_1, pos_2, {"air"})
if #spawn_pos_list > 0 then
return spawn_pos_list[math.random(1, #spawn_pos_list)]
else
return nil
end
end

View File

@ -0,0 +1,29 @@
function petz.blood(self)
if not(petz.settings.blood) or self.no_blood then
return
end
local pos = self.object:get_pos()
local texture
if self.blood_texture then
texture = self.blood_texture
else
texture = "petz_blood.png"
end
local gravity = -9.8
minetest.add_particlespawner({
amount = 5,
time = 0.25,
minpos = pos,
maxpos = pos,
minvel = {x = -1, y = -1, z = -1},
maxvel = {x = 1, y = 1, z = 1},
minacc = {x = 0, y = gravity, z = 0},
maxacc = {x = 0, y = gravity, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1,
texture = texture,
glow = 0
})
end

View File

@ -0,0 +1,16 @@
petz.bottled = function(self, clicker)
--capture the petz with the 'bottled' property in the bottle
local new_stack = ItemStack(self.bottled) -- add special mob egg with all mob information
local stack_meta = new_stack:get_meta()
local itemstack_meta = petz.capture(self, clicker, false)
stack_meta:set_int("petz:texture_no", itemstack_meta:get_int("texture_no"))
--minetest.chat_send_all("texture= "..itemstack_meta:get_int("texture_no"))
local inv = clicker:get_inventory()
if inv:room_for_item("main", new_stack) then
inv:add_item("main", new_stack)
inv:remove_item("main", "vessels:glass_bottle")
else
minetest.add_item(clicker:get_pos(), new_stack)
end
end

166
petz/petz/api/api_breed.lua Normal file
View File

@ -0,0 +1,166 @@
local S = ...
petz.breed = function(self, clicker, wielded_item, wielded_item_name)
if not(self.is_rut) and not(self.is_pregnant) then
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
self.is_rut = true
mobkit.remember(self, "is_rut", self.is_rut)
petz.do_particles_effect(self.object, self.object:get_pos(), "heart")
mokapi.make_sound("object", self.object, "petz_"..self.type.."_moaning", petz.settings.max_hear_distance)
else
if self.is_rut then
minetest.chat_send_player(clicker:get_player_name(), S("This animal is already rut."))
else
minetest.chat_send_player(clicker:get_player_name(), S("This animal is already pregnant."))
end
end
end
petz.pony_breed = function(self, clicker, wielded_item, wielded_item_name)
if wielded_item_name == "petz:glass_syringe" and self.is_male then
local new_wielded_item = ItemStack("petz:glass_syringe_sperm")
local meta = new_wielded_item:get_meta()
local speedup = (self.horseshoes or 0) * petz.settings.horseshoe_speedup
meta:set_string("petz_type", self.type)
meta:set_int("max_speed_forward", (self.max_speed_forward - speedup))
meta:set_int("max_speed_reverse", (self.max_speed_reverse - speedup))
meta:set_int("accel", (self.accel - speedup))
if wielded_item:get_count() > 1 then
local inv = clicker:get_inventory()
if not inv:room_for_item("main", new_wielded_item) then
minetest.chat_send_player(clicker:get_player_name(), S("No room in your inventory for a Glass Syringe with seed."))
return
end
wielded_item:take_item(1)
clicker:set_wielded_item(wielded_item)
inv:add_item("main", new_wielded_item)
else
clicker:set_wielded_item(new_wielded_item)
end
elseif wielded_item_name == "petz:glass_syringe_sperm" and not(self.is_male) then
local meta = wielded_item:get_meta()
local petz_type = meta:get_string("petz_type")
if not(self.is_pregnant) and self.pregnant_count > 0 and self.type == petz_type then
self.is_pregnant = mobkit.remember(self, "is_pregnant", true)
local pregnant_count = self.pregnant_count - 1
mobkit.remember(self, "pregnant_count", pregnant_count)
local max_speed_forward = meta:get_int("max_speed_forward")
local max_speed_reverse = meta:get_int("max_speed_reverse")
local accel = meta:get_int("accel")
local father_veloc_stats = {}
father_veloc_stats["max_speed_forward"] = max_speed_forward
father_veloc_stats["max_speed_reverse"] = max_speed_reverse
father_veloc_stats["accel"] = accel
self.father_veloc_stats = mobkit.remember(self, "father_veloc_stats", father_veloc_stats)
petz.do_particles_effect(self.object, self.object:get_pos(), "pregnant".."_"..self.type)
clicker:set_wielded_item("petz:glass_syringe")
end
end
end
petz.childbirth = function(self)
local pos = self.object:get_pos()
self.is_pregnant = mobkit.remember(self, "is_pregnant", false)
self.pregnant_time = mobkit.remember(self, "pregnant_time", 0.0)
local baby_properties = {}
baby_properties["baby_born"] = true
if self.father_genes then
baby_properties["gen1_father"] = self.father_genes["gen1"]
baby_properties["gen2_father"] = self.father_genes["gen2"]
else
baby_properties["gen1_father"] = math.random(1, #self.skin_colors-1)
baby_properties["gen2_father"] = math.random(1, #self.skin_colors-1)
end
if self and self.genes then
baby_properties["gen1_mother"] = self.genes["gen1"]
baby_properties["gen2_mother"] = self.genes["gen2"]
else
baby_properties["gen1_mother"] = math.random(1, #self.skin_colors-1)
baby_properties["gen2_mother"] = math.random(1, #self.skin_colors-1)
end
local baby_type = "petz:"..self.type
if self.type == "elephant" then -- female elephants have "elephant" as type
if math.random(1, 2) == 1 then
baby_type = "petz:elephant_female" --could be a female baby elephant
end
end
pos.y = pos.y + 1.01 -- birth a litte up
local baby = minetest.add_entity(pos, baby_type, minetest.serialize(baby_properties))
mokapi.make_sound("object", baby, "petz_pop_sound", petz.settings.max_hear_distance)
local baby_entity = baby:get_luaentity()
baby_entity.is_baby = true
mobkit.remember(baby_entity, "is_baby", baby_entity.is_baby)
if not(self.owner== nil) and not(self.owner== "") then
baby_entity.tamed = true
mobkit.remember(baby_entity, "tamed", baby_entity.tamed)
baby_entity.owner = self.owner
mobkit.remember(baby_entity, "owner", baby_entity.owner)
end
return baby_entity
end
petz.pregnant_timer = function(self, dtime)
self.pregnant_time = mobkit.remember(self, "pregnant_time", self.pregnant_time + dtime)
if self.pregnant_time >= petz.settings.pregnancy_time then
local baby_entity = petz.childbirth(self)
if self.is_mountable then
--Set the genetics accordingly the father and the mother
local speedup = (self.horseshoes or 0) * petz.settings.horseshoe_speedup
local random_number = math.random(-1, 1)
local new_max_speed_forward = petz.round(((self.father_veloc_stats["max_speed_forward"] or 1) + (self.max_speed_forward-speedup))/2) + random_number
if new_max_speed_forward <= 0 then
new_max_speed_forward = 0
elseif new_max_speed_forward > 10 then
new_max_speed_forward = 10
end
random_number = math.random(-1, 1)
local new_max_speed_reverse = petz.round(((self.father_veloc_stats["max_speed_reverse"] or 1) + (self.max_speed_reverse-speedup))/2) + random_number
if new_max_speed_reverse <= 0 then
new_max_speed_reverse = 0
elseif new_max_speed_reverse > 10 then
new_max_speed_reverse = 10
end
random_number = math.random(-1, 1)
local new_accel = petz.round(((self.father_veloc_stats["accel"] or 1) + (self.accel-speedup))/2) + random_number
if new_accel <= 0 then
new_accel = 0
elseif new_accel > 10 then
new_accel = 10
end
baby_entity.max_speed_forward = new_max_speed_forward
mobkit.remember(baby_entity, "max_speed_forward", baby_entity.max_speed_forward)
baby_entity.max_speed_reverse = new_max_speed_reverse
mobkit.remember(baby_entity, "max_speed_reverse", baby_entity.max_speed_reverse)
baby_entity.accel = new_accel
mobkit.remember(baby_entity, "accel", baby_entity.accel)
end
end
end
petz.growth_timer = function(self, dtime)
self.growth_time = mobkit.remember(self, "growth_time", (self.growth_time or 0) + dtime)
if self.growth_time >= petz.settings.growth_time then
self.is_baby = mobkit.remember(self, "is_baby", false)
local pos = self.object:get_pos()
pos.y = pos.y + 1.01 -- grows a litte up
self.object:set_pos(pos)
local obj
if self.parents then -- for chicken only
mokapi.remove_mob(self)
obj = minetest.add_entity(pos, self.parents[math.random(1, #self.parents)])
else
obj = self.object
petz.set_properties(self, {
jump = false,
is_baby = false,
visual_size = self.visual_size,
collisionbox = self.collisionbox
})
end
local vel = obj:get_velocity()
vel.y=vel.y + 4.0
obj:set_velocity(vel)
mokapi.make_sound("object", obj, "petz_pop_sound", petz.settings.max_hear_distance)
end
end

View File

@ -0,0 +1,25 @@
local S = ...
petz.brush = function(self, wielded_item_name, pet_name)
if petz.settings.tamagochi_mode then
if wielded_item_name == "petz:hairbrush" then
if not self.brushed then
petz.set_affinity(self, petz.settings.tamagochi_brush_rate)
self.brushed = true
mobkit.remember(self, "brushed", self.brushed)
else
minetest.chat_send_player(self.owner, S("Your").." "..S(pet_name).." "..S("had already been brushed."))
end
else --it's beaver_oil
if not self.beaver_oil_applied then
petz.set_affinity(self, petz.settings.tamagochi_beaver_oil_rate)
self.beaver_oil_applied = true
mobkit.remember(self, "beaver_oil_applied", self.beaver_oil_applied)
else
minetest.chat_send_player(self.owner, S("Your").." "..S(pet_name).." "..S("had already been spreaded with beaver oil."))
end
end
end
mokapi.make_sound("object", self.object, "petz_brushing", petz.settings.max_hear_distance)
petz.do_particles_effect(self.object, self.object:get_pos(), "star")
end

View File

@ -0,0 +1,138 @@
local S = ...
--
-- Register Egg
--
petz.create_pet = function(placer, itemstack, pet_name, pos)
local meta = itemstack:get_meta()
local staticdata = meta:get_string("staticdata")
local mob = minetest.add_entity(pos, pet_name, staticdata)
local self = mob:get_luaentity()
if not(self.is_wild) and not(self.owner) then --not monster and not owner
mokapi.set_owner(self, placer:get_player_name()) --set owner
petz.after_tame(self)
end
itemstack:take_item() -- since mob is unique we remove egg once spawned
return self
end
function petz:register_egg(pet_name, desc, inv_img, tamed)
local description = S("@1", desc)
if tamed then
description = description .." ("..S("Tamed")..")"
end
minetest.register_craftitem(pet_name .. "_set", { -- register new spawn egg containing mob information
description = description,
inventory_image = inv_img,
groups = {spawn_egg = 2},
stack_max = 1,
on_place = function(itemstack, placer, pointed_thing)
local spawn_pos = pointed_thing.above
-- am I clicking on something with existing on_rightclick function?
local under = minetest.get_node(pointed_thing.under)
local def = minetest.registered_nodes[under.name]
if def and def.on_rightclick then
return def.on_rightclick(pointed_thing.under, under, placer, itemstack)
end
if spawn_pos and not minetest.is_protected(spawn_pos, placer:get_player_name()) then
if not minetest.registered_entities[pet_name] then
return
end
spawn_pos = petz.pos_to_spawn(pet_name, spawn_pos)
petz.create_pet(placer, itemstack, pet_name, spawn_pos)
end
return itemstack
end,
})
end
petz.check_capture_items = function(self, wielded_item_name, clicker, check_inv_room)
if self.driver then
return
end
local capture_item_type
if wielded_item_name == petz.settings.lasso then
capture_item_type = "lasso"
elseif (wielded_item_name == "mobs:net") or (wielded_item_name == "fireflies:bug_net") then
capture_item_type = "net"
else
return false
end
if capture_item_type == self.capture_item then
if check_inv_room then
--check for room in inventory
local inv = clicker:get_inventory()
if inv:room_for_item("main", ItemStack("air")) then
return true
else
minetest.chat_send_player(clicker:get_player_name(), S("No room in your inventory to capture it."))
return false
end
else
return true
end
else
return false
end
end
petz.capture = function(self, clicker, put_in_inventory)
self.captured = mobkit.remember(self, "captured", true) --IMPORTANT! mark as captured
local new_stack = ItemStack(self.name .. "_set") -- add special mob egg with all mob information
--Save the staticdata into the ItemStack-->
local stack_meta = new_stack:get_meta()
local ent = self.object:get_luaentity()
local staticdata = ent:get_staticdata(self)
stack_meta:set_string("staticdata", staticdata)
--Info text stuff for the ItemStack
local info_text = ""
if not(petz.str_is_empty(self.tag)) then
info_text = info_text.."\n"..S("Name")..": "..self.tag
end
if self.breed then
local genre
if self.is_male then
genre = "Male"
else
genre = "Female"
end
info_text = info_text.."\n"..S("Gender")..": "..S(genre)
end
if self.skin_colors then
info_text = info_text.."\n"..S("Color")..": "..S(petz.first_to_upper(self.skin_colors[self.texture_no]))
end
if self.is_mountable then
info_text = info_text.."\n"..S("Speed Stats")..": " ..self.max_speed_forward.."/"..self.max_speed_reverse.."/"..self.accel
end
if self.is_pregnant then
info_text = info_text.."\n"..S("It is pregnant")
end
local description
if self.description then
description = self.description
else
description = self.type
end
stack_meta:set_string("description", S(petz.first_to_upper(description)).." ("..S("Tamed")..")"..info_text)
if put_in_inventory then
local inv = clicker:get_inventory()
if inv:room_for_item("main", new_stack) then
inv:add_item("main", new_stack)
else
minetest.add_item(clicker:get_pos(), new_stack)
end
end
if self.type == "bee" and self.behive then
petz.decrease_total_bee_count(self.behive)
local meta, honey_count, bee_count = petz.get_behive_stats(self.behive)
petz.set_infotext_behive(meta, honey_count, bee_count)
end
petz.remove_tamed_by_owner(self, false)
mokapi.remove_mob(self)
return stack_meta
end

View File

@ -0,0 +1,12 @@
petz.get_collisionbox = function(p1, p2, scale_model, scale_baby)
p1 = vector.multiply(p1, scale_model)
p2 = vector.multiply(p2, scale_model)
local collisionbox = {p1.x, p1.y, p1.z, p2.x, p2.y, p2.z}
local collisionbox_baby
if scale_baby then
local p1b = vector.multiply(p1, scale_baby)
local p2b = vector.multiply(p2, scale_baby)
collisionbox_baby = {p1b.x, p1b.y, p1b.z, p2b.x, p2b.y, p2b.z}
end
return collisionbox, collisionbox_baby
end

View File

@ -0,0 +1,21 @@
petz.get_color_group = function(item_name)
local color_name
local name
for _, row in ipairs(dye.dyes) do
name = row[1]
color_name = "color_" .. name
if minetest.get_item_group(item_name, color_name) > 0 then
break
end
end
name = name:gsub("%_", "")
return name
end
petz.colorize = function(self, color)
local background_texture = "petz_"..self.type.."_background.png"
local overlay_texture = "(petz_"..self.type.."_overlay.png^[colorize:"..color..":125)"
local colorized_texture = background_texture .."^"..overlay_texture
petz.set_properties(self, {textures = {colorized_texture}})
self.colorized = mobkit.remember(self, "colorized", color)
end

View File

@ -0,0 +1,3 @@
petz.colors = {}
petz.colors["green"] = "#3ADF00"
petz.colors["red"] = "#DF013A"

View File

@ -0,0 +1,24 @@
local S = ...
petz.convert = function(self, player_name)
local old_pet_name = petz.first_to_upper(self.type)
self.convert_count = self.convert_count - 1
mobkit.remember(self, "convert_count", self.convert_count)
if self.convert_count <= 0 then
local pos = self.object:get_pos()
local converted_pet = minetest.add_entity(pos, petz.settings[self.type.."_convert_to"])
mokapi.make_sound("object", converted_pet, "petz_pop_sound", petz.settings.max_hear_distance)
local converted_entity = converted_pet:get_luaentity()
converted_entity.tamed = true
mobkit.remember(converted_entity, "tamed", converted_entity.tamed)
converted_entity.owner = player_name
mobkit.remember(converted_entity, "owner", converted_entity.owner)
mokapi.remove_mob(self)
local new_pet_name = petz.first_to_upper(converted_entity.type)
minetest.chat_send_player(player_name , S("The").." "..S(old_pet_name).." "..S("turn into").." "..S(new_pet_name))
else
minetest.chat_send_player(player_name , S("The").." "..S(old_pet_name).." "..S("is turning into another animal")..".")
mokapi.make_sound("object", self.object, "petz_"..self.type.."_moaning", petz.settings.max_hear_distance)
petz.do_particles_effect(self.object, self.object:get_pos(), "heart")
end
end

View File

@ -0,0 +1,29 @@
local modpath = ...
--
--Create Dam Beaver Mechanics
--
petz.create_dam = function(self, pos)
if petz.settings.beaver_create_dam and not(self.dam_created) then --a beaver can create only one dam
if math.random(1, 60000) > 1 then --chance of the dam to be created
return false
end
local pos_underwater = { --check if water below (when the beaver is still terrestrial but float in the surface of the water)
x = pos.x,
y = pos.y - 4.5,
z = pos.z,
}
if minetest.get_node(pos_underwater).name == "default:sand" then
local pos_dam = { --check if water below (when the beaver is still terrestrial but float in the surface of the water)
x = pos.x,
y = pos.y - 2.0,
z = pos.z,
}
minetest.place_schematic(pos_dam, modpath..'/schematics/beaver_dam.mts', 0, nil, true)
self.dam_created = true
return true
end
end
return false
end

View File

@ -0,0 +1,4 @@
petz.get_os_month = function()
local nowTable= os.date('*t')
return nowTable.month
end

View File

@ -0,0 +1,121 @@
local S = ...
--
-- Dreamcatcher (protector for Petz)
--
-- Dreamcatcher
minetest.register_craftitem("petz:dreamcatcher", {
description = S("Pet Dreamcatcher"),
inventory_image = "petz_dreamcatcher.png",
groups = {},
on_use = function (itemstack, user, pointed_thing)
local user_name = user:get_player_name()
local user_pos = user:get_pos()
minetest.show_formspec(user_name, "petz:form_dreamcatcher", petz.create_form_list_by_owner_dreamcatcher(user_name, user_pos))
end,
})
minetest.register_craft({
type = "shaped",
output = "petz:dreamcatcher",
recipe = {
{"", "group:wood", ""},
{"farming:string", "farming:string", "farming:string"},
{"petz:ducky_feather", "petz:ducky_feather", "petz:ducky_feather"},
}
})
petz.put_dreamcatcher = function(self, clicker, wielded_item, wielded_item_name)
if self.dreamcatcher then
minetest.chat_send_player(clicker:get_player_name(), S("This pet already has a Dreamcatcher."))
return
end
wielded_item:take_item() --quit one from player's inventory
clicker:set_wielded_item(wielded_item)
self.dreamcatcher = true
mobkit.remember(self, "dreamcatcher", self.dreamcatcher)
mokapi.make_sound("object", self.object, "petz_magical_chime", petz.settings.max_hear_distance)
petz.do_particles_effect(self.object, self.object:get_pos(), "dreamcatcher")
end
petz.drop_dreamcatcher = function(self)
if self.dreamcatcher then --drop the dreamcatcher
minetest.add_item(self.object:get_pos(), "petz:dreamcatcher")
mokapi.make_sound("object", self.object, "petz_pop_sound", petz.settings.max_hear_distance)
self.dreamcatcher = false
mobkit.remember(self, "dreamcatcher", self.dreamcatcher)
end
end
petz.dreamcatcher_save_metadata = function(self)
if not(self.dreamcatcher) or self.tag == "" or not(self.owner) then
return
end
local item_list_table = petz.tamed_by_owner[self.owner]
if not(item_list_table) then
return
end
for i = 1, #item_list_table do
if item_list_table[i].pet == self then
item_list_table[i]["metadata"].tag = self.tag
item_list_table[i]["metadata"].type = self.type
item_list_table[i]["metadata"].dreamcatcher = self.dreamcatcher
item_list_table[i]["metadata"].last_pos = self.object:get_pos()
break
end
end
end
petz.create_form_list_by_owner_dreamcatcher = function(user_name, user_pos)
--Get the values of the list
local item_list_table = petz.tamed_by_owner[user_name]
if item_list_table then
if #item_list_table <= 0 then
minetest.chat_send_player(user_name, "You have no pets with a name and a dreamcatcher to list.")
return ''
end
local item_list = ""
--local text_color
for key, pet_table in ipairs(item_list_table) do
local pet = pet_table.pet
local pet_type
local pet_pos
local pet_tag
local list_pet = false
if mobkit.is_alive(pet) and pet.dreamcatcher then -- check if alive and has a dreamcatcher
pet_tag = pet.tag
pet_type = pet.type
pet_pos = pet.object:get_pos()
--text_color = petz.colors["green"]
list_pet = true
elseif pet_table.metadata.dreamcatcher then
pet_tag = pet_table.metadata.tag
pet_type = pet_table.metadata.type
pet_pos = pet_table.metadata.last_pos
--text_color = petz.colors["red"]
list_pet = true
end
if list_pet and pet_pos then
pet_type = pet_type:gsub("^%l", string.upper)
local distance, pet_pos_x, pet_pos_y, pet_pos_z
distance = tostring(petz.round(vector.distance(user_pos, pet_pos)))
pet_pos_x = tostring(math.floor(pet_pos.x+0.5))
pet_pos_y = tostring(math.floor(pet_pos.y+0.5))
pet_pos_z = tostring(math.floor(pet_pos.z+0.5))
item_list = item_list .. pet_tag.." | " .. S(pet_type) .. " | ".. "Pos = (".. pet_pos_x .. "/"
.. pet_pos_y .. "/".. pet_pos_z ..") | Dist= "..distance..","
end
end
local form_list_by_owner =
"size[6,8;]"..
--"style_type[textlist;textcolor="..text_color.."]"..
"image[2,0;1,1;petz_dreamcatcher.png]"..
"textlist[0,1;5,6;petz_list;"..item_list..";selected idx]"..
"button_exit[2,7;1,1;btn_exit;"..S("Close").."]"
return form_list_by_owner
else
return ''
end
end

View File

@ -0,0 +1,50 @@
petz.increase_egg_count = function(self)
self.eggs_count = mobkit.remember(self, "eggs_count", self.eggs_count+1)
end
--Lay Egg
petz.lay_egg = function(self)
if self.eggs_count >= petz.settings.max_laid_eggs then
return
end
if petz.isinliquid(self) then --do not put eggs when in liquid
return
end
local pos = self.object:get_pos()
if self.type_of_egg == "item" then
local lay_egg_timing = petz.settings.lay_egg_timing
if mobkit.timer(self, math.random(lay_egg_timing - (lay_egg_timing*0.2), lay_egg_timing+ (lay_egg_timing*0.2))) then
minetest.add_item(pos, "petz:"..self.type.."_egg") --chicken/duck/penguin egg!
petz.increase_egg_count(self)
end
end
if self.lay_eggs_in_nest then
local lay_range = 1
local nearby_nodes = minetest.find_nodes_in_area(
{x = pos.x - lay_range, y = pos.y - 1, z = pos.z - lay_range},
{x = pos.x + lay_range, y = pos.y + 1, z = pos.z + lay_range},
"petz:ducky_nest")
if #nearby_nodes > 1 then
local nest_type
if self.type == "hen" then
nest_type = "chicken"
else
nest_type = "ducky"
end
local nest_to_lay = nearby_nodes[math.random(1, #nearby_nodes)]
minetest.set_node(nest_to_lay, {name= "petz:"..nest_type.."_nest_egg"})
petz.increase_egg_count(self)
end
end
end
--Extract Egg from a Nest
petz.extract_egg_from_nest = function(pos, player, egg_type)
local inv = player:get_inventory()
if inv:room_for_item("main", egg_type) then
inv:add_item("main", egg_type) --add the egg to the player's inventory
minetest.set_node(pos, {name= "petz:ducky_nest"}) --Replace the node to a empty nest
else
minetest.chat_send_player(player:get_player_name(), "No room in your inventory for the egg.")
end
end

View File

@ -0,0 +1,37 @@
--
-- Enviromental Damage
--
function petz.env_damage(self, pos, prty)
local stand_pos= mobkit.get_stand_pos(self)
local stand_node_pos = mobkit.get_node_pos(stand_pos)
local stand_node = mobkit.nodeatpos(stand_node_pos)
if stand_node and stand_node.groups.igniter then --if lava or fire
mobkit.hurt(self, petz.settings.igniter_damage)
local air_pos = minetest.find_node_near(stand_pos, self.view_range, "air", false)
if air_pos then
mobkit.hq_goto(self, prty, air_pos)
end
end
if self.noxious_nodes then
for i = 1, #self.noxious_nodes do
local noxious_node = self.noxious_nodes[i]
local node_pos
if noxious_node.where then
if noxious_node.where == "stand" then
node_pos = stand_pos
elseif noxious_node.where == "entity" then
node_pos = pos
else
node_pos = pos
end
else
node_pos = pos
end
local node = minetest.get_node_or_nil(node_pos)
if node and node.name == noxious_node.name then
mobkit.hurt(self, noxious_node.damage or 1)
end
end
end
end

View File

@ -0,0 +1,103 @@
local S= ...
petz.insert_tamed_by_owner = function(self)
if not self.owner then
return
end
if (petz.tamed_by_owner[self.owner] == nil) then
petz.tamed_by_owner[self.owner] = {}
end
local insert = true
for i = 1, #petz.tamed_by_owner[self.owner] do
if petz.tamed_by_owner[self.owner][i].pet == self then
insert = false
break
end
end
if insert then --if not yet
table.insert(petz.tamed_by_owner[self.owner], {["pet"] = self, metadata = {["tag"] = self.tag, ["type"] = self.type, ["last_pos"] = nil}})
end
end
petz.remove_tamed_by_owner = function(self, force)
if self.tag ~= "" or force then
if petz.tamed_by_owner[self.owner] then
local temp_table = {}
for key, pet_table in ipairs(petz.tamed_by_owner[self.owner]) do
if pet_table.pet ~= self then
table.insert(temp_table, pet_table)
--minetest.chat_send_player("singleplayer", self.tag)
end
end
petz.tamed_by_owner[self.owner] = temp_table
end
end
end
petz.count_tamed_by_owner = function(owner_name)
local count
if petz.tamed_by_owner[owner_name] then
count = #petz.tamed_by_owner[owner_name]
else
count = 0
end
return count
end
petz.do_feed = function(self)
petz.set_affinity(self, petz.settings.tamagochi_feed_hunger_rate)
self.fed = mobkit.remember(self, "fed", true)
end
petz.after_tame = function(self)
petz.insert_tamed_by_owner(self)
if petz.settings.tamagochi_mode then
self.init_tamagochi_timer = true
end
end
--
--Tame with a whip mechanic
--
-- Whip/lashing behaviour
petz.do_lashing = function(self)
if not self.lashed then
self.lashed = mobkit.remember(self, "lashed", true)
end
mokapi.make_sound("object", self.object, "petz_"..self.type.."_moaning", petz.settings.max_hear_distance)
end
petz.tame_whip= function(self, hitter)
local wielded_item_name= hitter:get_wielded_item():get_name()
if (wielded_item_name == "petz:whip") then
if not self.tamed then
--The mob can be tamed lashed with a whip
self.lashing_count = self.lashing_count + 1
if self.lashing_count >= petz.settings.lashing_tame_count then
self.lashing_count = mobkit.remember(self, "lashing_count", 0) --reset to 0
mokapi.set_owner(self, hitter:get_player_name())
petz.after_tame(self)
minetest.chat_send_player(self.owner, S("The").." "..S(petz.first_to_upper(self.type)).." "..S("has been tamed."))
mobkit.clear_queue_high(self) -- do not attack
end
else
if (petz.settings.tamagochi_mode) and (self.owner == hitter:get_player_name()) then
petz.do_lashing(self)
end
end
mokapi.make_sound("object", hitter, "petz_whip", petz.settings.max_hear_distance)
end
end
--Ants
petz_feed_queen_ant= function(self, clicker, player_name, wielded_item)
local creative_mode = minetest.settings:get_bool("creative_mode")
if not creative_mode then -- if not in creative, take item
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
end
self.eggs_count = mobkit.remember(self, "eggs_count", 0)
minetest.chat_send_player(player_name, S("The Queen Ant will produce more eggs."))
end

564
petz/petz/api/api_forms.lua Normal file
View File

@ -0,0 +1,564 @@
local S = ...
local _context = {}
minetest.register_on_leaveplayer(function(player)
_context[player:get_player_name()] = nil
end)
local function create_context(player_name, tab_id)
_context[player_name] = {}
_context[player_name].tab_id = tab_id
end
petz.create_form = function(player_name, buy)
local pet = petz.pet[player_name]
local form_size = {w = 4, h = 3}
local buttonexit_pos = {x = 1, y = 6}
local hungrystuff_pos
local form_title
local tamagochi_form_stuff
local affinity_stuff = ''
local form_orders = ''
local more_form_orders = ''
local tab_form = ''
if not _context[player_name] then
create_context(player_name, 1)
end
local tab_id = _context[player_name].tab_id
local pet_icon = "petz_spawnegg_"..pet.type..".png"
if tab_id == 1 and not(buy) then
local pet_image_icon = "image[0.375,0.375;1,1;"..pet_icon.."]"
if pet.affinity == nil then
pet.affinity = 0
end
if petz.settings.tamagochi_mode then
form_size.w= form_size.w + 1
if pet.has_affinity then
form_title = S("Orders")
hungrystuff_pos = {x= 3, y = 2}
affinity_stuff =
"image_button[3.5,3.5;1,1;petz_affinity_heart.png;btn_affinity;]"..
"label[4.5,4;".. tostring(pet.affinity).."%]"
else
form_size.w= form_size.w
form_size.h= form_size.h + 1
form_title = S("Status")
hungrystuff_pos = {x= 1, y = 3}
end
tamagochi_form_stuff =
pet_image_icon ..
"label[1.375,3;".. form_title .."]"..
"image_button[".. (hungrystuff_pos.x+0.5) ..",".. (hungrystuff_pos.y +0.5)..";1,1;petz_pet_bowl_inv.png;btn_bowl;]"..
affinity_stuff
local health_label = S("Health").." = "..tostring(pet.hp)
local hungry_label
if not pet.fed then
hungry_label = S("Hungry")
else
hungry_label = S("Satiated")
end
hungry_label = hungry_label.."\n"..health_label
tamagochi_form_stuff = tamagochi_form_stuff .. "label[".. hungrystuff_pos.x +1.5 ..",".. (hungrystuff_pos.y+0.75) ..";"..hungry_label.."]"
else
if pet.has_saddlebag and pet.saddlebag then
form_size.w= form_size.w + 1
end
tamagochi_form_stuff = pet_image_icon
if pet.has_affinity then
tamagochi_form_stuff = tamagochi_form_stuff .. "label[1,2;".. S("Orders") .."]"
end
end
if pet.is_pet and pet.tamed then
if not(pet.tag) then
pet.tag = ""
end
if pet.dreamcatcher then
tamagochi_form_stuff = tamagochi_form_stuff..
"image_button_exit[4,0.375;1,1;petz_dreamcatcher.png;btn_dreamcatcher;]"
end
tamagochi_form_stuff = tamagochi_form_stuff..
"field[0.375,2;3,0.5;ipt_name;"..S("Name")..":"..";"..pet.tag.."]"..
"checkbox[3.5,1.75;btn_muted;"..S("Muted")..";"..petz.vartostring(pet.muted).."]"..
"checkbox[3.5,2.25;btn_show_tag;"..S("Show tag")..";"..petz.vartostring(pet.show_tag).."]"
end
local gender
if pet.is_male then
gender = S("Male")
else
gender = S("Female")
end
tamagochi_form_stuff = tamagochi_form_stuff..
"label[3,0.875;"..gender.."]"
if pet.breed then --Show the Gender
local pregnant_icon_x
local pregnant_icon_y
local pregnant_text_x
local pregnant_text_y
local infertile_text_x
local infertile_text_y
if pet.is_mountable or pet.give_orders then
pregnant_icon_x = 3
pregnant_icon_y = 5
pregnant_text_x = 4
pregnant_text_y = 5
infertile_text_x = 3
infertile_text_y = 5
else
pregnant_icon_x = 3
pregnant_icon_y = 2
pregnant_text_x = 4
pregnant_text_y = 2
infertile_text_x = 3
infertile_text_y = 3
end
if not(pet.is_male) and pet.is_pregnant then
local pregnant_remain_time = petz.round(petz.settings.pregnancy_time - pet.pregnant_time)
tamagochi_form_stuff = tamagochi_form_stuff..
"image["..(pregnant_icon_x+0.375)..","..(pregnant_icon_y+0.5)..";1,1;petz_"..pet.type.."_pregnant_icon.png]"..
"label["..(pregnant_text_x+0.375)..","..(pregnant_text_y+1)..";"..S("Pregnant").." ("..tostring(pregnant_remain_time).."s)]"
elseif not(pet.is_male) and pet.pregnant_count and pet.pregnant_count <= 0 then
tamagochi_form_stuff = tamagochi_form_stuff..
"label["..(infertile_text_x+0.5)..","..(infertile_text_y+1)..";"..S("Infertile").."]"
end
if pet.is_baby then
local growth_remain_time = petz.round(petz.settings.growth_time - pet.growth_time)
tamagochi_form_stuff = tamagochi_form_stuff..
"label["..(pregnant_text_x-0.5)..","..(pregnant_text_y+1)..";"..S("To adult").." ("..tostring(growth_remain_time).."s)]"
end
end
if pet.type == "pony" then
local horseshoes = pet.horseshoes or 0
more_form_orders = more_form_orders..
"image_button_exit[5,0.375;1,1;petz_horseshoe.png;btn_horseshoes;"..tostring(horseshoes).."]"
end
if pet.can_perch then
form_size.h = form_size.h + 1
buttonexit_pos.y = buttonexit_pos.y + 1
more_form_orders = more_form_orders..
"button_exit[0.375,6.5;1,1;btn_alight;"..S("Alight").."]" ..
"button_exit[1.375,6.5;1,1;btn_fly;"..S("Fly").."]"..
"button_exit[2.375,6.5;2,1;btn_perch_shoulder;"..S("Perch on shoulder").."]"
elseif pet.is_mountable then
more_form_orders = more_form_orders..
"image[3.5,4.5;1,1;petz_"..pet.type.."_velocity_icon.png]"..
"label[4.5,5;".. tostring(pet.max_speed_forward).."/"..tostring(pet.max_speed_reverse)..'/'..tostring(pet.accel).."]"
if pet.has_saddlebag and pet.saddlebag then
more_form_orders = more_form_orders..
"image_button[5,0.375;1,1;petz_saddlebag.png;btn_saddlebag;]"
end
end
if pet.give_orders then
form_size.h= form_size.h + 4
form_size.w= form_size.w + 1
form_orders =
"button_exit[0.375,3.5;3,1;btn_followme;"..S("Follow me").."]"..
"button_exit[0.375,4.5;3,1;btn_standhere;"..S("Stand here").."]"..
"button_exit[0.375,5.5;3,1;btn_ownthing;"..S("Do your own thing").."]"..
more_form_orders
else
if petz.settings.tamagochi_mode then
buttonexit_pos.y = buttonexit_pos.y - 2
form_size.h= form_size.h + 1
else
buttonexit_pos.y = buttonexit_pos.y - 4
form_size.w= form_size.w + 1
end
end
if pet.is_wild then
form_orders = form_orders .. "button_exit[3.375,5.5;2,1;btn_guard;"..S("Guard").."]"
end
tab_form = tamagochi_form_stuff.. form_orders
elseif tab_id == 1 and buy then
form_size.w = form_size.w + 1
form_size.h = form_size.h + 2
buttonexit_pos.x = buttonexit_pos.x + 1
buttonexit_pos.y = buttonexit_pos.y - 2
local item_description
local item_inventory_image
if petz.settings.selling_exchange_items_list[pet.exchange_item_index] then
item_description = petz.settings.selling_exchange_items_list[pet.exchange_item_index].description or ""
item_inventory_image = petz.settings.selling_exchange_items_list[pet.exchange_item_index].inventory_image or ""
else
item_description = ""
item_inventory_image = ""
end
local item_amount = pet.exchange_item_amount or 1
tab_form = tab_form ..
"label[0.375,1.85;"..S("Cost")..": ]"..
"label[2,1.85;"..item_description.."]"..
"image[2.5,0.375;1,1;"..item_inventory_image.."]"..
"label[0.375,2.5;"..S("Amount")..":]"..
"label[2,2.5;"..tostring(item_amount).."]"..
"style_type[button_exit;bgcolor=#333600;textcolor=white]"..
"button_exit[2,3.25;2,1;btn_buy;"..S("Buy").."]"
elseif tab_id == 2 and not(buy) then
form_size.w = form_size.w + 1
form_size.h = form_size.h + 2
buttonexit_pos.y = buttonexit_pos.y - 2
if pet.owner then
tab_form = "image_button[0.375,0.375;1,1;"..pet_icon.."^petz_abandon_icon.png;btn_abandon;]"
if pet.herd then
tab_form = tab_form .. "checkbox[0.375,1.75;btn_herding;"..S("Herding")..";"..petz.vartostring(pet.herding).."]"
end
if petz.check_lifetime(pet) then
tab_form = tab_form .. "image[2,0.375;1,1;petz_lifetime.png]" .. "label[3,0.75;"..S("Lifetime").."]".."label[3,1;"..tostring(pet.lifetime).."]"
end
end
elseif (tab_id == 3 and not(buy) and pet.dreamcatcher) then
form_size.w = form_size.w + 2
form_size.h = form_size.h + 1
buttonexit_pos.y = buttonexit_pos.y - 3
tab_form = tab_form ..
"checkbox[0.25,1.5;btn_back_home;"..S("Automatic Go back home")..";"..petz.vartostring(pet.back_home).."]"..
"label[1.3,0.75;<< "..S("Click to set the home").."]"..
"image_button_exit[0.25,0.25;1,1;petz_kennel.png;btn_set_home;"..S("Set").."\n"..S("Home").."]"
if pet.home_pos then
tab_form = tab_form ..
"label[0.25,2.0;"..S("Home Pos")..": x="..tostring(petz.truncate(pet.home_pos.x,1))
..", y="..petz.truncate(pet.home_pos.y,1)..", z="..petz.truncate(pet.home_pos.z,1).."]"
end
elseif (tab_id ==3 or tab_id ==4) and petz.settings.selling and not(buy) then
form_size.w = form_size.w + 1
form_size.h = form_size.h + 2
buttonexit_pos.y = buttonexit_pos.y - 2
local exchange_items = ''
local dropdown_index = 1
for i = 1, #petz.settings.selling_exchange_items_list do
local description = petz.settings.selling_exchange_items_list[i].description
if description then
if i > 1 then
exchange_items = exchange_items .. ","
end
exchange_items = exchange_items .. description
if i == pet.exchange_item_index then
dropdown_index = i
end
end
end
tab_form = tab_form ..
"checkbox[0.375,0.5;chk_for_sale;"..S("For Sale")..";"..petz.vartostring(pet.for_sale).."]"..
"label[0.375,1.0;"..S("Item").."]"..
"textlist[0.375,1.25;3,3;txtlst_exchange_items;"..exchange_items..";"..tostring(dropdown_index).."]"..
"label[4,1;"..S("Amount").."]"..
"field[4,1.25;1,0.45;fld_exchange_item_amount;;"..tostring(pet.exchange_item_amount).."]"
--"scrollbaroptions[min=1;max=99;arrows=show;smallstep=1;largestep=1]"..
--"scrollbar[4,1.0;0.45,0.45;vertical;scrbar_exchange_item_amount;10]"
end
--Tab Header
local tab_main = S("Main")
local tab_other = S("Other")
local tab_shop = S("Shop")
local tab_home = S("Home")
local tab_header
if buy then
tab_header = tab_shop
else
tab_header = tab_main..","..tab_other
if pet.dreamcatcher then
tab_header = tab_header..","..tab_home
end
if not(minetest.is_singleplayer()) then
tab_header = tab_header..","..tab_shop
end
end
--minetest.chat_send_player("singleplayer", tab_header)
local final_form =
"size["..(form_size.w+0.875)..","..(form_size.h+1)..";]"..
"real_coordinates[true]"..
"tabheader[0,0;tabheader;"..tab_header..";"..tostring(tab_id)..";true;false]"..
tab_form..
"style_type[button_exit;bgcolor=#006699;textcolor=white]"..
"button_exit["..(buttonexit_pos.x+0.5)..","..(buttonexit_pos.y+0.75)..";1,1;btn_close;"..S("Close").."]"
return final_form
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if (formname ~= "petz:form_orders") then
return false
end
local player_name = player:get_player_name()
-- Was a tab selected?
if fields.tabheader then
local tab_id = tonumber(fields.tabheader)
if tab_id > 0 then
create_context(player_name, tab_id)
minetest.show_formspec(player_name, "petz:form_orders", petz.create_form(player_name, false))
end
return
end
local pet = petz.pet[player_name]
if pet and pet.object then
if fields.btn_followme then
petz.follow(pet, player)
elseif fields.btn_standhere then
petz.standhere(pet)
elseif fields.btn_guard then
petz.guard(pet)
elseif fields.btn_ownthing then
mobkit.clear_queue_low(pet)
petz.ownthing(pet)
elseif fields.btn_alight then
petz.alight(pet, 0, "stand")
elseif fields.btn_fly then
mobkit.clear_queue_low(pet)
mobkit.clear_queue_high(pet)
pet.status = nil
petz.hq_fly(pet, 0)
minetest.after(2.5, function()
if mobkit.is_alive(pet) then
mobkit.clear_queue_low(pet)
pet.object:set_acceleration({ x = 0, y = 0, z = 0 })
pet.object:set_velocity({ x = 0, y = 0, z = 0 })
end
end, pet)
elseif fields.btn_perch_shoulder then
petz.standhere(pet)
mobkit.animate(pet, "stand")
local shoulder_pos
if pet.type == "parrot" then
shoulder_pos = {x= 0.5, y= -6.25, z=0}
else
shoulder_pos = {x= 0.5, y= -6.0, z=0}
end
pet.object:set_attach(player, "Arm_Left", shoulder_pos, {x=0, y=0, z=180})
pet.object:set_properties({physical = false,})
minetest.after(120.0, function()
if mobkit.is_alive(pet) then
pet.object:set_detach()
pet.object:set_properties({physical = true,})
end
end, pet)
elseif fields.btn_muted then
pet.muted= mobkit.remember(pet, "muted", minetest.is_yes(fields.btn_muted))
elseif fields.btn_show_tag then
pet.show_tag = mobkit.remember(pet, "show_tag", minetest.is_yes(fields.btn_show_tag))
elseif fields.btn_dreamcatcher then
petz.drop_dreamcatcher(pet)
elseif fields.btn_saddlebag then
--Load the inventory from the petz
local inv = minetest.get_inventory({ type="detached", name="saddlebag_inventory" })
inv:set_list("saddlebag", {})
if pet.saddlebag_inventory then
for key, value in pairs(pet.saddlebag_inventory) do
inv:set_stack("saddlebag", key, value)
end
end
--Show the inventory:
local formspec = "size[8,8;]"..
"image[3,0;1,1;petz_saddlebag.png]"..
"label[4,0;"..S("Saddlebag").."]"..
"list[detached:saddlebag_inventory;saddlebag;0,1;8,2;]"..
"list[current_player;main;0,4;8,4;]"
minetest.show_formspec(player_name, "petz:saddlebag_inventory", formspec)
elseif fields.btn_bowl then
minetest.show_formspec(player_name, "petz:food_form", petz.create_food_form(pet))
elseif fields.btn_affinity then
minetest.show_formspec(player_name, "petz:affinity_form", petz.create_affinity_form(pet))
elseif fields.btn_horseshoes then
petz.horseshoes_reset(pet)
elseif fields.btn_abandon then
minetest.show_formspec(player_name, "petz:abandon_form", petz.get_abandon_confirmation())
elseif fields.btn_herding then
pet.herding = mobkit.remember(pet, "herding", minetest.is_yes(fields.btn_herding))
elseif fields.chk_for_sale then
pet.for_sale = mobkit.remember(pet, "for_sale", minetest.is_yes(fields.chk_for_sale))
elseif fields.fld_exchange_item_amount or fields.txtlst_exchange_items then
local event = minetest.explode_textlist_event(fields.txtlst_exchange_items)
if event.type == "CHG" then
--minetest.chat_send_all(event.index)
pet.exchange_item_index = mobkit.remember(pet, "exchange_item_index", event.index)
end
pet.exchange_item_amount = mobkit.remember(pet, "exchange_item_amount", mokapi.delimit_number( tonumber(fields.fld_exchange_item_amount), {min=1, max=99}) or 1)
elseif fields.btn_buy then
petz.buy(pet, player)
elseif fields.btn_back_home then
pet.back_home= mobkit.remember(pet, "back_home", minetest.is_yes(fields.btn_back_home))
elseif fields.btn_set_home then
pet.home_pos= mobkit.remember(pet, "home_pos", pet.object:get_pos())
create_context(player_name, 3)
minetest.show_formspec(player_name, "petz:form_orders", petz.create_form(player_name, false))
end
if fields.ipt_name then
pet.tag = minetest.formspec_escape(string.sub(fields.ipt_name, 1 , 12))
mobkit.remember(pet, "tag", pet.tag)
if not(pet.tag == "") then
petz.insert_tamed_by_owner(pet)
else
petz.remove_tamed_by_owner(pet, true)
end
end
petz.update_nametag(pet)
_context[player_name] = nil
return true
else
_context[player_name] = nil
return false
end
end)
--On receive fields
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "petz:saddlebag_inventory" then
return false
end
--Save the saddlebag content
local player_name = player:get_player_name()
local ent = petz.pet[player_name]
if ent and ent.object then
local inv = minetest.get_inventory({ type="detached", name="saddlebag_inventory" })
local itemstacks_table = {}
local inv_size = inv:get_size("saddlebag")
if inv_size > 0 then
for i = 1, inv_size do
itemstacks_table[i] = inv:get_stack("saddlebag", i):to_table()
end
ent.saddlebag_inventory = itemstacks_table
mobkit.remember(ent, "saddlebag_inventory", itemstacks_table)
end
end
return true
end)
--Saddlebag detached inventory
local function allow_put(pos, listname, index, stack, player)
return stack:get_count()
end
petz.create_detached_saddlebag_inventory = function(name)
local saddlebag_inventory = minetest.create_detached_inventory(name, {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
local stack = inv:get_stack(from_list, from_index)
return allow_put(inv, from_list, from_index, stack, player)
end,
allow_put = function(inv, listname, index, stack, player)
return stack:get_count()
end,
allow_take = function(inv, listname, index, stack, player)
return stack:get_count()
end,
})
-- Size and width of saddlebag inventory
saddlebag_inventory:set_size("saddlebag", 16)
saddlebag_inventory:set_width("saddlebag", 8)
end
petz.create_detached_saddlebag_inventory("saddlebag_inventory")
petz.create_food_form = function(self)
local items = string.split(petz.settings[self.type.."_follow"], ',')
local items_desc = ""
for i = 1, #items do --loop thru all items
local item = petz.str_remove_spaces(items[i]) --remove spaces
if string.sub(item, 1, 5) == "group" then
items_desc = items_desc .. string.sub(item, 7)
else
items_desc = items_desc .. (minetest.registered_items[item].description or "unknown")
end
if i < #items then
items_desc = items_desc .. ", "
end
end
local form_size = {w= 3, h= 3}
local button_exit = {x= 1, y= 2}
if self.breed then
form_size.h = form_size.h + 1
button_exit.y = button_exit.y + 1
end
local formspec =
"size["..form_size.w..","..form_size.h.."]"..
"image[0,0;1,1;petz_spawnegg_"..self.type..".png]"..
"label[1,0;"..S("Food").."]"..
"label[0,1;"..S("It likes")..": ".. items_desc .."]"..
"button_exit["..button_exit.x..","..button_exit.y..";1,1;btn_exit;"..S("Close").."]"
if self.breed then
local breed_item = minetest.registered_items[petz.settings[self.type.."_breed"]]
local breed_item_desc
if not(breed_item) then
if self.is_mountable then
breed_item_desc = minetest.registered_items["petz:glass_syringe"].description
else
breed_item_desc = "unknown"
end
else
breed_item_desc = breed_item.description
end
formspec = formspec .. "label[0,2;"..S("It breeds with")..": ".. breed_item_desc .."]"
end
return formspec
end
petz.create_affinity_form = function(self)
local form_size = {w= 3, h= 4}
local button_exit = {x= 1, y= 3}
local feed_status, feed_status_color
if self.fed then
feed_status = S("Fed")
feed_status_color = petz.colors["green"]
else
feed_status = S("Hungry")..": " .. tostring(petz.calculate_affinity_change(-petz.settings.tamagochi_feed_hunger_rate))
feed_status_color = petz.colors["red"]
end
local brushing_status, brushing_status_color
if self.brushed then
brushing_status = S("Brushed")
brushing_status_color = petz.colors["green"]
else
brushing_status = S("Not brushed")..": " .. tostring(petz.calculate_affinity_change(-petz.settings.tamagochi_brush_rate))
brushing_status_color = petz.colors["red"]
end
local formspec =
"size["..form_size.w..","..form_size.h.."]"..
"image[0,0;1,1;petz_affinity_heart.png]"..
"label[1,0;"..S("Affinity").."]"..
"label[0,1;".. minetest.colorize(feed_status_color, feed_status).."]"..
"label[0,2;".. minetest.colorize(brushing_status_color, brushing_status).."]"..
"button_exit["..button_exit.x..","..button_exit.y..";1,2;btn_exit;"..S("Close").."]"
return formspec
end
--On receive fields
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "petz:food_form" and formname ~= "petz:affinity_form" then
return false
end
local player_name = player:get_player_name()
local pet = petz.pet[player_name]
if pet and (mobkit.is_alive(pet)) then
create_context(player_name, 1)
minetest.show_formspec(player_name, "petz:form_orders", petz.create_form(player_name, false))
end
return true
end)
function petz.get_abandon_confirmation()
local text = S("Do you want to ABANDON your pet?!")
local formspec = {
"size[6,2.476]",
"real_coordinates[true]",
"label[0.375,0.5;", minetest.formspec_escape(text), "]",
"style_type[button_exit;bgcolor=#006699;textcolor=white]",
"button_exit[1.2,1.3;1,0.8;btn_yes;"..S("Yes").."]"..
"button_exit[3.2,1.3;1.5,0.8;btn_cancel;"..S("Cancel").."]"
}
return table.concat(formspec, "")
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "petz:abandon_form" then
return false
end
local player_name = player:get_player_name()
if fields.btn_yes then
local pet = petz.pet[player_name]
if pet and (mobkit.is_alive(pet)) then
local msg = S("You've abandoned your").." "..pet.type
petz.abandon_pet(pet, msg)
end
else
create_context(player_name, 2)
minetest.show_formspec(player_name, "petz:form_orders", petz.create_form(player_name, false))
end
return true
end)

View File

@ -0,0 +1,93 @@
--
--Helper Functions
--
petz.set_properties = function(self, properties)
if type(self) == 'table' then
self = self.object
end
self:set_properties(properties)
end
function petz.is_night()
local timeofday = minetest.get_timeofday()
if timeofday == nil then --can be nil if world not loaded!!!
return nil
end
timeofday = timeofday * 24000
if (timeofday < 4500) or (timeofday > 19500) then
return true
else
return false
end
end
function petz.isinliquid(self)
local pos = self.object:get_pos()
pos.y = pos.y - 0.5
local node = mobkit.nodeatpos(pos)
if node and node.drawtype == 'liquid' then
return true
else
return false
end
end
function petz.round(x)
return x>=0 and math.floor(x+0.5) or math.ceil(x-0.5)
end
function petz.truncate(number, decimals)
local power = 10^decimals
return math.floor(number * power) / power
end
function petz.vartostring(var)
if var or var == 1 or var == "true" then
return "true"
elseif not(var) or var == nil or var == 0 or var == "false" then
return "false"
else
return "false"
end
end
function petz.set_list(list)
local set = {}
for _, l in ipairs(list) do set[l] = true end
return set
end
petz.pos_front_player = function(player)
local pos = player:get_pos()
local yaw = player:get_look_horizontal()
local dir_x = -math.sin(yaw) + 0.5
local dir_z = math.cos(yaw) + 0.5
local pos_front_player = { -- what is in front of mob?
x = pos.x + dir_x,
y = pos.y + 0.5,
z = pos.z + dir_z
}
return pos_front_player
end
petz.first_to_upper = function(str)
return (str:gsub("^%l", string.upper))
end
petz.str_is_empty = function(str)
return str == nil or str == ''
end
petz.is_pos_nan = function(pos)
if minetest.is_nan(pos.x) or minetest.is_nan(pos.y) or minetest.is_nan(pos.z) then
return true
else
return false
end
end
petz.str_remove_spaces = function(str)
str = str:gsub("%s+", "")
return str
end

View File

@ -0,0 +1,56 @@
local S = ...
petz.put_horseshoe = function(self, clicker)
if self.horseshoes >= 4 then
minetest.chat_send_player(clicker:get_player_name(), S("This pony has already four horseshoes."))
return
end
local wielded_item = clicker:get_wielded_item()
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
petz.horseshoes_inc_speed(self)
mokapi.make_sound("object", self.object, "petz_put_sound", petz.settings.max_hear_distance)
mokapi.make_sound("object", self.object, "petz_"..self.type.."_moaning", petz.settings.max_hear_distance)
end
petz.speedup_change = function(self, speedup)
self.max_speed_forward = self.max_speed_forward + speedup
self.max_speed_reverse = self.max_speed_reverse + speedup
self.accel= self.accel + speedup
end
petz.horseshoes_speedup = function(self)
if self.horseshoes == 0 then
return
end
local speedup = self.horseshoes * petz.settings.horseshoe_speedup
petz.speedup_change(self, speedup)
end
petz.horseshoes_inc_speed = function(self)
local speedup
if self.horseshoes > 0 then --first reset old speed up
speedup = self.horseshoes * petz.settings.horseshoe_speedup
petz.speedup_change(self, -speedup)
end
self.horseshoes = mobkit.remember(self, "horseshoes", (self.horseshoes+1)) --now inc the horseshoes
speedup = self.horseshoes * petz.settings.horseshoe_speedup --new speedup
petz.speedup_change(self, speedup)
end
petz.horseshoes_reset = function(self)
if self.horseshoes == 0 then
return
end
local speedup = self.horseshoes * petz.settings.horseshoe_speedup
petz.speedup_change(self, -speedup)
local obj
local pos = self.object:get_pos()
for i = 1, self.horseshoes do
obj = minetest.add_item(pos, "petz:horseshoe")
mokapi.drop_velocity(obj)
end
self.horseshoes = mobkit.remember(self, "horseshoes", 0)
mokapi.make_sound("object", self.object, "petz_pop_sound", petz.settings.max_hear_distance)
end

View File

@ -0,0 +1,350 @@
--
--'set_initial_properties' is call by 'on_activate' for each pet
--
petz.dyn_prop = {
accel = {type= "int", default = 1},
affinity = {type= "int", default = 100},
anthill_founded = {type= "boolean", default = false},
back_home = {type= "boolean", default = false},
beaver_oil_applied = {type= "boolean", default = false},
behive = {type= "pos", default = nil},
brushed = {type= "boolean", default = false},
captured = {type= "boolean", default = false},
child = {type= "boolean", default = false},
colorized = {type= "string", default = nil},
convert = {type= "string", default = nil},
convert_to = {type= "string", default = nil},
convert_count = {type= "int", default = 5},
dreamcatcher = {type= "boolean", default = false},
dead = {type= "boolean", default = false},
driver = {type= "player", default = nil},
eggs_count = {type= "int", default = 0},
exchange_item_index = {type= "int", default = 1},
exchange_item_amount = {type= "int", default = 1},
father_genes = {type= "table", default = {}},
father_veloc_stats = {type= "table", default = {}},
fed = {type= "boolean", default = true},
food_count = {type= "int", default = 0},
food_count_wool = {type= "int", default = 0},
for_sale = {type= "boolean", default = false},
gallop = {type= "boolean", default = false},
gallop_time = {type= "int", default = 0},
gallop_exhausted = {type= "boolean", default = false},
gallop_recover_time = {type= "int", default = petz.settings.gallop_recover_time},
genes = {type= "table", default = {}},
growth_time = {type= "int", default = 0},
herding = {type= "boolean", default = false},
home_pos = {type= "table", default = nil},
horseshoes = {type= "int", default = 0},
is_baby = {type= "boolean", default = false},
is_male = {type= "boolean", default = false},
is_pregnant = {type= "boolean", default = false},
is_rut = {type= "boolean", default = false},
lashed = {type= "boolean", default = false},
lashing_count = {type= "int", default = 0},
lifetime = {type= "int", default = nil},
max_speed_forward = {type= "int", default = 1},
max_speed_reverse = {type= "int", default = 1},
milked = {type= "boolean", default = false},
muted = {type= "boolean", default = false},
owner = {type= "string", default = nil},
pregnant_count = {type= "int", default = petz.settings.pregnant_count},
pregnant_time = {type= "int", default = 0},
saddle = {type= "boolean", default = false},
saddlebag = {type= "boolean", default = false},
saddlebag_inventory = {type= "table", default = {}},
shaved = {type= "boolean", default = false},
show_tag = {type= "boolean", default = false},
sleep_start_time = {type= "int", default = nil},
sleep_end_time = {type= "int", default = nil},
square_ball_attached = {type= "boolean", default = false},
status = {type= "string", default = nil},
tag = {type= "string", default = ""},
tamed = {type= "boolean", default = false},
--texture_no = {type= "int", default = 1}, --do not use!!! OR MISSING TEXTURE
warn_attack = {type= "boolean", default = false},
was_killed_by_player = {type= "boolean", default = false},
}
petz.compose_texture= function(self)
local texture
if self.type == "lamb" then
local shaved_string = ""
if self.shaved then
shaved_string = "_shaved"
end
texture = "petz_lamb".. shaved_string .."_"..self.skin_colors[self.texture_no]..".png"
elseif self.is_mountable then
if self.saddle then
texture = "petz_"..self.type.."_"..self.skin_colors[self.texture_no]..".png" .. "^petz_"..self.type.."_saddle.png"
else
texture = "petz_"..self.type.."_"..self.skin_colors[self.texture_no]..".png"
end
if self.saddlebag then
texture = texture .. "^petz_"..self.type.."_saddlebag.png"
end
else
texture = self.textures[self.texture_no]
end
return texture
end
petz.cleanup_prop= function(self)
self.warn_attack = false --reset the warn attack
self.driver = nil --no driver
self.was_killed_by_player = false --reset the warn attack
end
petz.genetics_random_texture = function(self, textures_count)
local array = {}
for row=1, textures_count do
array[row] = {}
for col=1, textures_count do
array[row][col] = math.min(row, col)
end
end
return array[math.random(1, textures_count)][math.random(1, textures_count)]
-- Accessing the array to calculate the rates
--local rates = {}
--for row=1, textures_count do
--for col=1, textures_count do
--rates[array[row][col]] = (rates[array[row][col]] or 0) + 1
--end
--end
--for row=1, textures_count do
--minetest.chat_send_player("singleplayer", tostring(rates[row]))
--end
end
petz.set_random_gender = function()
if math.random(1, 2) == 1 then
return true
else
return false
end
end
petz.get_gen = function(self)
local textures_count
if self.mutation and (self.mutation > 0) then
textures_count = #self.skin_colors - self.mutation
else
textures_count = #self.skin_colors
end
return math.random(1, textures_count)
end
petz.genetics_texture = function(self, textures_count)
for i = 1, textures_count do
if self.genes["gen1"] == i or self.genes["gen2"] == i then
return i
end
end
end
petz.load_vars = function(self)
for key, value in pairs(petz.dyn_prop) do
self[key] = mobkit.recall(self, key) or value["default"]
end
if not(self.sleep_start_time) or not(self.sleep_end_time) then
petz.calculate_sleep_times(self)
end
petz.insert_tamed_by_owner(self)
petz.cleanup_prop(self) --Reset some vars
end
function petz.set_initial_properties(self, staticdata, dtime_s)
--minetest.chat_send_all(staticdata)
local static_data_table = minetest.deserialize(staticdata)
local captured_mob = false
local baby_born = false
--TO DELETE IN FUTURE VERSIONS-->
local static_table_name
if static_data_table and static_data_table["memory"] then
static_table_name = "memory"
else
static_table_name = "fields"
end
--<
if static_data_table and static_data_table[static_table_name] and static_data_table[static_table_name]["captured"] then
captured_mob = true
elseif static_data_table and static_data_table["baby_born"] then
baby_born = true
end
--
--1. NEW MOBS
--
--dtime_s == 0 differenciates between loaded and new created mobs
if dtime_s == 0 and not captured_mob then --set some vars
--Load default settings ->
for key, value in pairs(petz.dyn_prop) do
self[key] = value["default"]
end
--Define some settings ->
--Set a random gender for all the mobs (not defined in the entity definition)
self.is_male = mobkit.remember(self, "is_male", petz.set_random_gender())
if self.is_mountable then
if not(baby_born) then
self.max_speed_forward= mobkit.remember(self, "max_speed_forward", math.random(2, 4)) --set a random velocity for walk and run
self.max_speed_reverse= mobkit.remember(self, "max_speed_reverse", math.random(1, 2))
self.accel= mobkit.remember(self, "accel", math.random(2, 4))
end
end
if self.parents then --for chicken only
self.is_baby = mobkit.remember(self, "is_baby", true)
end
--Mobs that can have babies
if self.breed then
--Genetics
local genes_mutation = false
if self.mutation and (self.mutation > 0) and math.random(1, 200) == 1 then
genes_mutation = true
end
if not genes_mutation then
if not baby_born then
self.genes["gen1"] = petz.get_gen(self)
self.genes["gen2"] = petz.get_gen(self)
--minetest.chat_send_player("singleplayer", tostring(self.genes["gen1"]))
--minetest.chat_send_player("singleplayer", tostring(self.genes["gen2"]))
else
if math.random(1, 2) == 1 then
self.genes["gen1"] = static_data_table["gen1_father"]
else
self.genes["gen1"] = static_data_table["gen2_father"]
end
if math.random(1, 2) == 1 then
self.genes["gen2"] = static_data_table["gen1_mother"]
else
self.genes["gen2"] = static_data_table["gen2_mother"]
end
end
local textures_count
if self.mutation and (self.mutation > 0) then
textures_count = #self.skin_colors - self.mutation
else
textures_count = #self.skin_colors
end
self.texture_no = petz.genetics_texture(self, textures_count)
else -- mutation
local mutation_gen = math.random((#self.skin_colors-self.mutation+1), #self.skin_colors) --select the mutation in the last skins
self.genes["gen1"] = mutation_gen
self.genes["gen2"] = mutation_gen
self.texture_no = mutation_gen
end
mobkit.remember(self, "genes", self.genes)
end
--ALL the mobs
--Get a texture
if not self.texture_no then
if self.skin_colors then
local textures_count
if self.mutation and (self.mutation > 0) then
textures_count = #self.skin_colors - self.mutation
else
textures_count = #self.skin_colors
end
self.texture_no = petz.genetics_random_texture(self, textures_count)
else
self.texture_no = 1
end
end
if petz.settings[self.type.."_convert_count"] then
self.convert_count = mobkit.remember(self, "convert_count", petz.settings[self.type.."_convert_count"])
end
if self.init_tamagochi_timer then
petz.init_tamagochi_timer(self)
end
petz.calculate_sleep_times(self) --Sleep behaviour
--
--2. ALREADY EXISTING MOBS
--
elseif not captured_mob then
petz.load_vars(self) --Load memory variables
--
--3. CAPTURED MOBS
--
else
self.captured = mobkit.remember(self, "captured", false) --IMPORTANT! mark as not captured
for key, value in pairs(petz.dyn_prop) do
local prop_value
if value["type"] == "string" then
prop_value = static_data_table[static_table_name][key]
elseif value["type"] == "int" then
prop_value = tonumber(static_data_table[static_table_name][key])
elseif value["type"] == "boolean" then
prop_value = minetest.is_yes(static_data_table[static_table_name][key])
elseif value["type"] == "table" then
prop_value = minetest.deserialize(static_data_table[static_table_name][key])
elseif value["type"] == "player" then
prop_value = nil
end
self[key] = mobkit.remember(self, key, prop_value) or value["default"]
end
end
--Custom textures
if captured_mob or self.breed then
local texture= petz.compose_texture(self) --compose the texture
mobkit.remember(self, "texture_no", self.texture_no)
petz.set_properties(self, {textures = {texture}})
end
if self.type == "bee" and self.queen then --delay to create beehive
minetest.after(math.random(120, 150), function()
if mobkit.is_alive(self.object) then
self.create_beehive = mobkit.remember(self, "create_beehive", true)
end
end, self)
elseif self.type == "ant" and self.ant_type == "queen" then
minetest.after(math.random(120, 150), function()
if mobkit.is_alive(self.object) then
self.create_anthill = mobkit.remember(self, "create_anthill", true)
end
end, self)
end
if self.colorized then
if not self.shaved then
petz.colorize(self, self.colorized)
end
end
--DELETE THIS BLOCK IN THE NEXT UPDATE -- FOR COMPATIBIITY PURPOSES FOR OLD CHICKENS ONLY>>>
if self.type == "chicken" then
self.is_baby = mobkit.remember(self, "is_baby", true)
self.texture_no = mobkit.remember(self, "texture_no", 1)
petz.set_properties(self, {textures = {self.textures[1]}})
end
--<<<
if self.horseshoes and not captured_mob then
petz.horseshoes_speedup(self)
end
if self.breed then
if baby_born then
self.is_baby = mobkit.remember(self, "is_baby", true)
end
if self.is_baby then
petz.set_properties(self, {
visual_size = self.visual_size_baby,
collisionbox = self.collisionbox_baby
})
end
end
--self.head_rotation = {x= -90, y= 90, z= 0}
--self.whead_position = self.object:get_bone_position("parent")
--self.head_position.y = self.head_position.y + 0.25
--ALL the mobs
if self.is_pet and self.tamed then
petz.update_nametag(self)
end
if self.status then
if self.status == "stand" then
petz.standhere(self)
elseif self.status == "guard" then
petz.guard(self)
elseif self.status == "sleep" then
self.status = nil --reset
else
self.status = nil
end
end
end

View File

@ -0,0 +1,33 @@
petz.check_lifetime = function(self)
local pet_lifetime = petz.settings[self.type.."_lifetime"]
--minetest.chat_send_all("test")
if self.dreamcatcher or (petz.settings.lifetime_only_non_tamed and self.tamed) or (petz.settings.lifetime_avoid_non_breedable and self.breed) then
return false
elseif petz.settings.lifetime > 0 and not(pet_lifetime and pet_lifetime < 0) then
--minetest.chat_send_all("test1")
return petz.settings.lifetime
elseif pet_lifetime and pet_lifetime > 0 then
--minetest.chat_send_all("test2")
return pet_lifetime
else
--minetest.chat_send_all("test3")
return false
end
end
petz.lifetime_timer = function(self, lifetime, on_step_time)
if not(self.lifetime) then
--Firstly apply the variability
local variability = lifetime * (math.random(0, petz.settings.lifetime_variability*100) / 100)
if math.random(1, 2) == 1 then
variability = -variability
end
lifetime = mokapi.round(lifetime - variability)
self.lifetime = mobkit.remember(self, "lifetime", lifetime)
end
--minetest.chat_send_all(tostring(self.lifetime))
self.lifetime = mobkit.remember(self, "lifetime", self.lifetime - on_step_time)
if self.lifetime <= 0 then
petz.on_die(self)
end
end

View File

@ -0,0 +1,90 @@
--
-- Mount Engine
--
petz.mount = function(self, clicker, wielded_item, wielded_item_name)
if clicker:is_player() then
local player_pressed_keys = clicker:get_player_control()
if player_pressed_keys["sneak"] then
return true
end
end
if self.tamed and self.owner == clicker:get_player_name() then
if self.driver and clicker == self.driver then -- detatch player already riding horse
petz.detach(clicker, {x = 1, y = 0, z = 1})
if self.wagon then
petz.animate_wagon(self, "stand")
end
mobkit.clear_queue_low(self)
mobkit.clear_queue_high(self)
mobkit.animate(self, "still")
return false
elseif (self.saddle or self.saddlebag or self.wagon) and wielded_item_name == petz.settings.shears then
if self.wagon then
self.wagon:remove()
mokapi.drop_item(self, "petz:wagon", 1)
self.wagon = nil
end
if self.saddle then
minetest.add_item(self.object:get_pos(), "petz:saddle")
mokapi.make_sound("object", self.object, "petz_pop_sound", petz.settings.max_hear_distance)
self.saddle = false
mobkit.remember(self, "saddle", self.saddle)
end
if self.saddlebag then
minetest.add_item(self.object:get_pos(), "petz:saddlebag")
mokapi.make_sound("object", self.object, "petz_pop_sound", petz.settings.max_hear_distance)
self.saddlebag = false
mobkit.remember(self, "saddlebag", self.saddlebag)
end
petz.set_properties(self, {textures = {"petz_"..self.type.."_"..self.skin_colors[self.texture_no]..".png"}})
return false
elseif (not(self.driver) and not(self.is_baby)) and ((wielded_item_name == "petz:saddle") or (wielded_item_name == "petz:saddlebag")) then -- Put on saddle if tamed
local put_saddle = false
if wielded_item_name == "petz:saddle" and not(self.saddle) then
put_saddle = true
elseif wielded_item_name == "petz:saddlebag" and not(self.saddlebag) and not(self.type == "pony") then
put_saddle = true
end
if put_saddle then
petz.put_saddle(self, clicker, wielded_item, wielded_item_name)
return false
end
elseif not(self.driver) and (self.saddle or self.wagon) then -- Mount petz
petz.set_properties(self, {stepheight = 1.1})
petz.attach(self, clicker)
return false
else
return true
end
else
return true
end
end
petz.put_saddle = function(self, clicker, wielded_item, wielded_item_name)
local saddle_type
local another_saddle = ""
if wielded_item_name == "petz:saddle" then
saddle_type = "saddle"
self.saddle = true
mobkit.remember(self, "saddle", self.saddle)
if self.saddlebag then
another_saddle = "^petz_"..self.type.."_saddlebag.png"
end
else
saddle_type = "saddlebag"
self.saddlebag = true
mobkit.remember(self, "saddlebag", self.saddlebag)
if self.saddle then
another_saddle = "^petz_"..self.type.."_saddle.png"
end
end
local texture = "petz_"..self.type.."_"..self.skin_colors[self.texture_no]..".png" .. "^petz_"..self.type.."_"..saddle_type..".png"..another_saddle
petz.set_properties(self, {textures = {texture}})
if not minetest.settings:get_bool("creative_mode") then
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
end
mokapi.make_sound("object", self.object, "petz_put_sound", petz.settings.max_hear_distance)
end

View File

@ -0,0 +1,24 @@
petz.update_nametag = function(self)
local name_tag
if self.show_tag and self.tag and not(self.tag == "") then
name_tag = self.tag
local _bgcolor
if not petz.settings["tag_background"] then
_bgcolor = "#FFFFFF00"
else
_bgcolor = false
end
self.object:set_nametag_attributes({
text = name_tag ..""..tostring(self.hp).."/"..tostring(self.max_hp),
bgcolor = _bgcolor,
})
else
self.object:set_nametag_attributes({
text = "",
})
end
end
petz.delete_nametag = function(self)
self.object:set_nametag_attributes({text = nil,})
end

View File

@ -0,0 +1,3 @@
function petz.on_deactivate(self)
petz.dreamcatcher_save_metadata(self)
end

View File

@ -0,0 +1,112 @@
--
--on_die event for all the mobs
--
petz.on_die = function(self)
self.dead = mobkit.remember(self, "dead", true) --a variable, useful to avoid functions
if self.object:get_hp() > 0 then --you can call this function directally
self.object:set_hp(0)
end
local pos = self.object:get_pos()
--Specific of each mob-->
if self.is_mountable then
if self.saddle then -- drop saddle when petz is killed while riding
minetest.add_item(pos, "petz:saddle")
end
if self.saddlebag then -- drop saddlebag
minetest.add_item(pos, "petz:saddlebag")
end
--Drop the items from petz inventory
local inv = minetest.get_inventory({ type="detached", name="saddlebag_inventory" })
inv:set_list("saddlebag", {})
if self.saddlebag_inventory then
for key, value in pairs(self.saddlebag_inventory) do
inv:set_stack("saddlebag", key, value)
end
for i = 1, inv:get_size("saddlebag") do
local stack = inv:get_stack("saddlebag", i)
if stack:get_count() > 0 then
minetest.item_drop(stack, self.object, pos)
end
end
end
--Drop horseshoes-->
if self.horseshoes and self.horseshoes > 0 then
mokapi.drop_item(self, "petz:horseshoe", self.horseshoes)
end
--If mounted, force unmount-->
if self.driver then
petz.force_detach(self.driver)
end
--If wagon, detach-->
if self.wagon then
self.wagon:set_detach()
end
elseif self.type == "puppy" then
if self.square_ball_attached and self.attached_squared_ball then
self.attached_squared_ball.object:set_detach()
end
end
--Make it not pointable-->
self.object:set_properties({
pointable = false,
})
--Check if Dreamctacher to drop it-->
petz.drop_dreamcatcher(self)
--Flying mobs fall down-->
if self.can_fly then
self.can_fly = false
end
--For all the mobs-->
local props = self.object:get_properties()
props.collisionbox[2] = props.collisionbox[1] - 0.0625
self.object:set_properties({collisionbox=props.collisionbox})
--Drop Items-->
mokapi.drop_items(self, self.was_killed_by_player or nil)
mobkit.clear_queue_high(self)
--Remove the owner entry for right_click formspec and close the formspec (it could be opened)-->
if petz.pet[self.owner] then
petz.pet[self.owner]= nil
minetest.close_formspec(self.owner, "petz:form_orders")
end
--Remove this petz from the list of the player pets-->
if self.tamed then
petz.remove_tamed_by_owner(self, false)
end
--Make Sound-->
mobkit.make_sound(self, 'die')
--Particles Effect
if petz.settings.death_effect then
minetest.add_particlespawner({
amount = 20,
time = 0.001,
minpos = pos,
maxpos = pos,
minvel = vector.new(-2,-2,-2),
maxvel = vector.new(2,2,2),
minacc = {x=0, y=0, z=0},
maxacc = {x=0, y=0, z=0},
minexptime = 1.1,
maxexptime = 1.5,
minsize = 1,
maxsize = 2,
collisiondetection = false,
vertical = false,
texture = "petz_smoke.png",
})
end
--To finish, the Mobkit Die Function-->
mobkit.hq_die(self)
end
petz.was_killed_by_player = function(self, puncher)
if self.hp <= 0 then
if puncher:is_player() then
return true
else
return false
end
else
return false
end
end

View File

@ -0,0 +1,123 @@
petz.puncher_is_player = function(puncher)
if type(puncher) == 'userdata' and puncher:is_player() then
return true
else
return false
end
end
petz.calculate_damage = function(self, time_from_last_punch, tool_capabilities)
local tool_damage = tool_capabilities.damage_groups.fleshy or 1
--minetest.chat_send_all(tostring("damage= "..tool_damage))
local time_bonus = (1 / time_from_last_punch)
if time_bonus > 1 then -- the second punch in less than 1 second
time_bonus= petz.round(time_bonus^0.33) --cubic root
else
time_bonus = 0
end
--minetest.chat_send_all(tostring(time_bonus))
local health_bonus = petz.round((self.max_hp / self.hp)^0.33)
--minetest.chat_send_all(tostring(health_bonus))
local luck_bonus = math.random(-1, 1)
--minetest.chat_send_all(tostring(luck_bonus))
local damage = tool_damage + time_bonus + health_bonus + luck_bonus
--minetest.chat_send_all(tostring(damage))
return damage
end
petz.kick_back= function(self, dir)
local hvel = vector.multiply(vector.normalize({x=dir.x, y=0, z=dir.z}), 4)
self.object:set_velocity({x=hvel.x, y=2, z=hvel.z})
end
petz.punch_tamagochi = function (self, puncher)
if self.affinity == nil then
return
end
if petz.settings.tamagochi_mode then
if self.owner == puncher:get_player_name() then
petz.set_affinity(self, -petz.settings.tamagochi_punch_rate)
end
end
end
--
--on_punch event for all the Mobs
--
function petz.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir)
local pos = self.object:get_pos() --pos of the petz
if not mobkit.is_alive(self) then --is petz alive
return
end
--Do not punch when you are mounted on it!!!-->
if self.is_mountable and puncher == self.driver then
return
end
--Check Dreamcatcher Protection
local puncher_is_player = petz.puncher_is_player(puncher)
if puncher_is_player then --player
if self.dreamcatcher and self.owner ~= puncher:get_player_name() then --The dreamcatcher protects the petz
return
end
else --no player
if self.dreamcatcher then
return
end
end
--Colorize Punch Effect-->
if petz.settings.colorize_punch then
local punch_texture = self.textures[self.texture_no].."^[colorize:"..petz.settings.punch_color..":125"
self.object:set_properties(self, {textures = {punch_texture}})
minetest.after(0.1, function()
if self then
self.object:set_properties(self, {textures = { petz.compose_texture(self) }})
end
end)
end
--Do Hurt-->
local damage = petz.calculate_damage(self, time_from_last_punch, tool_capabilities)
mobkit.hurt(self, damage)
--Tamagochi Mode?-->
petz.punch_tamagochi(self, puncher) --decrease affinity when in Tamagochi mode
--Check if killed by player and save it-->
self.was_killed_by_player = petz.was_killed_by_player(self, puncher)
--Update Nametag-->
petz.update_nametag(self)
--Kickback-->
petz.kick_back(self, dir)
--Sound-->
mokapi.make_sound("object", self.object, "petz_default_punch", petz.settings.max_hear_distance)
--Blood-->
petz.blood(self)
--Unmount?-->
if self.is_mountable and self.hp <= 0 and self.driver then --important for mountable petz!
petz.force_detach(self.driver)
end
--Lashing?-->
if self.is_wild then
petz.tame_whip(self, puncher)
end
--Warn Attack?-->
if self.is_wild and not(self.tamed) and not(self.attack_player) then --if you hit it, will attack player
self.warn_attack = true
mobkit.clear_queue_high(self)
end
--Monster Specific-->
if self.type == "mr_pumpkin" then --teleport to player's back
if math.random(1, 3) == 1 then
--petz.lookat(self, puncher:get_pos())
if (self.hp <= self.max_hp / 2) then
petz.bh_teleport(self, pos, puncher, puncher:get_pos())
else
mokapi.make_sound("object", self.object, "petz_fireball", petz.settings.max_hear_distance)
petz.spawn_throw_object(self.object, 20, "petz:ent_jack_o_lantern_grenade")
end
end
elseif self.type == "tarantula" then
if math.random(1, 5) == 1 then
--petz.lookat(self, puncher:get_pos())
petz.spawn_throw_object(self.object, 20, "petz:ent_cobweb")
end
end
end

View File

@ -0,0 +1,124 @@
local S = ...
--Context
--In this temporary table is saved the reference to an entity by its owner
--to show the when on_rightclick form is shown
petz.pet = {} -- A table of pet["owner_name"]= entity_ref
minetest.register_on_leaveplayer(function(player)
petz.pet[player:get_player_name()] = nil
end)
--
--on_rightclick event for all the Mobs
--
petz.on_rightclick = function(self, clicker)
if not(clicker:is_player()) then
return false
end
local pet_name = petz.first_to_upper(self.type)
local player_name = clicker:get_player_name()
local is_owner
if self.owner == player_name then
is_owner = true
else
is_owner = false
end
local privs = minetest.get_player_privs(player_name)
local wielded_item = clicker:get_wielded_item()
local wielded_item_name = wielded_item:get_name()
local show_form = false
local buy
if ((self.is_pet) and is_owner and (self.can_be_brushed)) -- If brushing or spread beaver oil
and ((wielded_item_name == "petz:hairbrush") or (wielded_item_name == "petz:beaver_oil")) then
petz.brush(self, wielded_item_name, pet_name)
--If feeded
elseif mokapi.feed(self, clicker, petz.settings.tamagochi_feed_hunger_rate, S("@1 at full health (@2)", S(petz.first_to_upper(self.type)), tostring(self.hp)), "moaning") then
if mokapi.tame(self, 5, player_name, S("@1 has been tamed!", S(petz.first_to_upper(self.type))), {max = petz.settings.max_tamed_by_owner, count= petz.count_tamed_by_owner(player_name), msg = S("You cannot tame more petz! (@1 max.)", tostring(petz.settings.max_tamed_by_owner))}) then
petz.after_tame(self)
end
if self.tamed then
petz.update_nametag(self)
end
if petz.settings.tamagochi_mode and not(self.fed) then
petz.do_feed(self)
end
petz.refill(self) --Refill wool, milk or nothing
--convert to
elseif not(petz.str_is_empty(petz.settings[self.type.."_convert"])) and not(petz.str_is_empty(petz.settings[self.type.."_convert_to"]))
and mokapi.item_in_itemlist(wielded_item_name, petz.settings[self.type.."_convert"]) then
petz.convert(self, player_name)
elseif petz.check_capture_items(self, wielded_item_name, clicker, true) then
if self.is_pet and (not(privs.server) and (not(petz.settings.rob_mobs) and (not(self.tamed) or (self.owner and self.owner ~= player_name)))) then
minetest.chat_send_player(player_name, S("You are not the owner of the").." "..S(pet_name)..".")
return
end
if self.owner== nil or self.owner== "" or (not(is_owner) and petz.settings.rob_mobs) then
mokapi.set_owner(self, player_name)
petz.after_tame(self)
end
petz.capture(self, clicker, true)
minetest.chat_send_player("singleplayer", S("Your").." "..S(pet_name).." "..S("has been captured")..".")
elseif self.breed and wielded_item_name == petz.settings[self.type.."_breed"] and not(self.is_baby) then
--minetest.chat_send_all("test="..petz.settings[self.type.."_breed"])
petz.breed(self, clicker, wielded_item, wielded_item_name)
elseif (wielded_item_name == "petz:dreamcatcher") and (self.tamed) and (self.is_pet) and is_owner then
petz.put_dreamcatcher(self, clicker, wielded_item, wielded_item_name)
elseif petz.settings[self.type.."_colorized"] and minetest.get_item_group(wielded_item_name, "dye") > 0 then --Colorize textures
local color_group = petz.get_color_group(wielded_item_name)
if color_group and not(self.shaved) then
petz.colorize(self, color_group)
end
--
--Pet Specifics
--below here
elseif self.type == "lamb" and is_owner then
if wielded_item_name == petz.settings.shears and clicker:get_inventory() and not self.shaved then
petz.lamb_wool_shave(self, clicker) --shear it!
else
show_form = true
end
elseif self.type == "ant" and self.ant_type == "queen" then
if wielded_item_name == "farming:seed_wheat" then
petz_feed_queen_ant(self, clicker, player_name, wielded_item)
end
elseif self.milkable and wielded_item_name == "bucket:bucket_empty" and clicker:get_inventory() then
if not(self.milked) then
petz.milk_milk(self, clicker)
else
minetest.chat_send_player(clicker:get_player_name(), S("This animal has already been milked."))
end
elseif (self.is_mountable) and (wielded_item_name == "petz:glass_syringe" or wielded_item_name == "petz:glass_syringe_sperm") then
if not(self.is_baby) then
petz.pony_breed(self, clicker, wielded_item, wielded_item_name)
end
elseif self.bottled and (wielded_item_name == "vessels:glass_bottle") then
petz.bottled(self, clicker)
elseif (self.type == "pony") and (wielded_item_name == "petz:horseshoe") and (self.owner == player_name) then
petz.put_horseshoe(self, clicker)
elseif (self.type == "pony") and (wielded_item_name == "petz:wagon") and (self.owner == player_name) then
petz.put_wagon(self, clicker)
elseif self.is_mountable and is_owner then
show_form = petz.mount(self, clicker, wielded_item, wielded_item_name)
elseif self.feathered and is_owner then
if wielded_item_name == petz.settings.shears and clicker:get_inventory() then
petz.cut_feather(self, clicker) --cut a feather
else
show_form = true
end
elseif petz.settings.selling and not(minetest.is_singleplayer()) and self.for_sale and self.owner and not(self.owner == player_name) then --Buy Form
buy = true
show_form = true
else --Else open the Form
if (self.is_pet) and ((self.tamed) and (self.owner == player_name)) then
buy = false
show_form = true
end
end
if show_form then
petz.pet[player_name]= self
minetest.show_formspec(player_name, "petz:form_orders", petz.create_form(player_name, buy))
end
end

View File

@ -0,0 +1,48 @@
petz.on_step = function(self, dtime)
local on_step_time = 1
if mobkit.timer(self, on_step_time) and not(self.dead) then --Only check every 1 sec, not every step!
if self.init_tamagochi_timer then
petz.init_tamagochi_timer(self)
end
if self.is_pregnant then
petz.pregnant_timer(self, on_step_time)
elseif self.is_baby then
petz.growth_timer(self, on_step_time)
end
if self.gallop then
petz.gallop(self, on_step_time)
end
--DELETE WHEN UPDATING TO 5.4-->
if not(self.on_deactivate) then
petz.dreamcatcher_save_metadata(self)
end
--<
local lifetime = petz.check_lifetime(self)
if lifetime then
petz.lifetime_timer(self, lifetime, on_step_time)
end
if self.dreamcatcher and self.back_home then
petz.back_home(self)
end
--Tamagochi
--Check the hungry
if petz.settings.tamagochi_mode and self.owner and self.is_pet and petz.settings.tamagochi_hungry_warning > 0 and not(self.status=="sleep") and petz.settings[self.type.."_follow"] then
if not(self.tmp_follow_texture) then
local items = string.split(petz.settings[self.type.."_follow"], ',')
local item = petz.str_remove_spaces(items[1]) --the first one
local follow_texture
if string.sub(item, 1, 5) == "group" then
follow_texture = "petz_pet_bowl_inv.png"
else
follow_texture = minetest.registered_items[item].inventory_image
end
self.tmp_follow_texture = follow_texture --temporary property
end
if mobkit.timer(self, 2) then
if (self.hp / self.max_hp) <= petz.settings.tamagochi_hungry_warning then
petz.do_particles_effect(self.object, self.object:get_pos(), "hungry", self.tmp_follow_texture)
end
end
end
end
end

View File

@ -0,0 +1,70 @@
petz.ownthing = function(self)
self.status = mobkit.remember(self, "status", nil)
if self.can_fly then
petz.hq_wanderfly(self, 0)
elseif self.can_swin and self.isinliquid then
mobkit.hq_aqua_roam(self, 0, self.max_speed)
else
mobkit.hq_roam(self, 0)
end
mobkit.clear_queue_low(self)
mobkit.clear_queue_high(self)
end
petz.stand = function(self)
self.object:set_velocity({ x = 0, y = 0, z = 0 })
self.object:set_acceleration({ x = 0, y = 0, z = 0 })
end
petz.standhere = function(self)
mobkit.clear_queue_high(self)
mobkit.clear_queue_low(self)
if self.can_fly then
if petz.node_name_in(self, "below") == "air" then
mobkit.animate(self, "fly")
else
mobkit.animate(self, "stand")
end
elseif self.can_swin and petz.isinliquid(self) then
mobkit.animate(self, "def")
else
if self.animation["sit"] and not(petz.isinliquid(self)) then
mobkit.animate(self, "sit")
else
mobkit.animate(self, "stand")
end
end
self.status = mobkit.remember(self, "status", "stand")
--mobkit.lq_idle(self, 2400)
petz.stand(self)
end
petz.guard = function(self)
self.status = mobkit.remember(self, "status", "guard")
mobkit.clear_queue_high(self)
petz.stand(self)
end
petz.follow = function(self, player)
mobkit.clear_queue_low(self)
mobkit.clear_queue_high(self)
self.status = mobkit.remember(self, "status", "follow")
if self.can_fly then
mobkit.animate(self, "fly")
petz.hq_followliquidair(self, 100, player)
elseif self.can_swin and self.isinliquid then
mobkit.animate(self, "def")
petz.hq_followliquidair(self, 100, player)
else
mobkit.hq_follow(self, 100, player)
end
end
petz.alight = function(self, prty, end_status)
mobkit.clear_queue_low(self)
mobkit.clear_queue_high(self)
if not(petz.node_name_in(self, "below") == "air") then
mobkit.animate(self, "fly")
end
petz.hq_alight(self, prty, end_status)
end

View File

@ -0,0 +1,108 @@
--
--Particle Effects
--
petz.do_particles_effect = function(obj, pos, particle_type, texture_name)
local minpos
minpos = {
x = pos.x,
y = pos.y,
z = pos.z
}
local maxpos
maxpos = {
x = minpos.x + 0.4,
y = minpos.y - 0.5,
z = minpos.z + 0.4
}
local time
local particles_amount
local min_size
local max_size
if particle_type == "star" then
texture_name = "petz_star_particle.png"
time = 1.5
particles_amount = 20
min_size = 1.0
max_size = 1.5
elseif particle_type == "heart" then
texture_name = "petz_affinity_heart.png"
time = 1.5
particles_amount = 10
min_size = 1.0
max_size = 1.5
elseif particle_type == "pregnant_pony" then
texture_name = "petz_pony_pregnant_icon.png"
time = 1.5
particles_amount = 10
min_size = 5.0
max_size = 6.0
elseif particle_type == "pregnant_lamb" then
texture_name = "petz_lamb_pregnant_icon.png"
time = 1.5
particles_amount = 10
min_size = 5.0
max_size = 6.0
elseif particle_type == "pregnant_camel" then
texture_name = "petz_camel_pregnant_icon.png"
time = 1.5
particles_amount = 10
min_size = 5.0
max_size = 6.0
elseif particle_type == "dreamcatcher" then
texture_name = "petz_dreamcatcher_particle.png"
time = 1.5
particles_amount = 15
min_size = 1.0
max_size = 2.0
elseif particle_type == "pollen" then
texture_name = "petz_pollen.png"
time = 1.5
particles_amount = 15
min_size = 0.5
max_size = 1.0
elseif particle_type == "pumpkin" then
texture_name = "petz_pumpkin_particle.png"
time = 1.5
particles_amount = 10
min_size = 2.0
max_size = 4.0
elseif particle_type == "fire" then
texture_name = "petz_fire_particle.png"
time = 1.5
particles_amount = 50
min_size = 2.0
max_size = 4.0
elseif particle_type == "sleep" then
texture_name = "petz_sleep_particle.png"
time = 1.5
particles_amount = 3
min_size = 1.0
max_size = 2.0
elseif particle_type == "hungry" then
time = 1.5
particles_amount = 3
min_size = 1.0
max_size = 2.0
end
minetest.add_particlespawner({
--attached = objw,
amount = particles_amount,
time = time,
minpos = minpos,
maxpos = maxpos,
--minvel = {x=1, y=0, z=1},
--maxvel = {x=1, y=0, z=1},
--minacc = {x=1, y=0, z=1},
--maxacc = {x=1, y=0, z=1},
minexptime = 1,
maxexptime = 1,
minsize = min_size,
maxsize =max_size,
collisiondetection = false,
vertical = false,
texture = texture_name,
glow = 14
})
end

View File

@ -0,0 +1,16 @@
--
--Poop Engine
--
petz.poop = function(self, pos)
if not(petz.settings.poop) or not(self.tamed) or not(self.poop) or self.child or petz.is_jumping(self) or not(petz.is_standing(self)) or math.random(1, petz.settings.poop_rate) > 1 then
return
end
local node_name_below = petz.node_name_in(self, "below")
local node_name = petz.node_name_in(self, "self")
--minetest.chat_send_player("singleplayer", node_name)
if node_name == "air" and node_name_below ~= "air" then
pos.y = pos.y - 0.75
minetest.set_node(pos, {name = "petz:poop"})
end
end

View File

@ -0,0 +1,36 @@
local S = ...
petz.buy = function(self, buyer)
local buyer_name= buyer:get_player_name()
local inv_buyer= buyer:get_inventory()
local seller_name = self.owner
if not seller_name then
return
end
local seller = minetest.get_player_by_name(seller_name)
local item_index = self.exchange_item_index
local item_amount = self.exchange_item_amount
local item_name = petz.settings.selling_exchange_items_list[item_index].name
--minetest.chat_send_all(item_name)
local item_description = petz.settings.selling_exchange_items_list[item_index].description
local item_stack = ItemStack({name = item_name, count = item_amount})
if not seller then
minetest.chat_send_player(buyer_name, S("The seller is not online."))
return
elseif not(inv_buyer:contains_item("main", item_stack)) then
minetest.chat_send_player(buyer_name, S("You have not").." "..item_description.." ("..tostring(item_amount)..")")
return
end
-- Do buy
inv_buyer:remove_item("main", item_stack)
local inv_seller = seller:get_inventory()
if inv_seller:room_for_item("main", item_stack) then
inv_seller:add_item("main", item_stack)
else
local seller_pos = seller:get_pos()
minetest.item_drop(item_stack, seller, seller_pos)
end
petz.abandon_pet(self, S("You have sold your").." "..self.type.." "..S("to").." "..buyer_name..".")
mokapi.set_owner(self, buyer_name)
minetest.chat_send_player(buyer_name, S("Congratulations, you've bought a").." "..self.type)
end

234
petz/petz/api/api_silk.lua Normal file
View File

@ -0,0 +1,234 @@
local S = ...
--Coocon
minetest.register_node("petz:cocoon", {
description = S("Silkworm Cocoon"),
inventory_image = "petz_cocoon_inv.png",
groups = {snappy=1, bendy=2, cracky=1},
sounds = default.node_sound_wood_defaults(),
paramtype = "light",
drawtype = "mesh",
mesh = 'petz_cocoon.b3d',
visual_scale = 1.0,
tiles = {"petz_cocoon.png"},
collision_box = {
type = "fixed",
fixed = {-0.125, -0.5, -0.375, 0.0625, -0.25, 0.3125},
},
selection_box = {
type = "fixed",
fixed = {-0.125, -0.5, -0.375, 0.0625, -0.25, 0.3125},
},
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
timer:start(math.random(400, 600))
end,
on_timer = function(pos)
if not minetest.registered_entities["petz:moth"] then
return
end
if pos and petz.is_night() then --only spawn at night, to it does not die
minetest.add_entity(pos, "petz:moth")
minetest.set_node(pos, {name= "air"})
return false
end
return true
end
})
--Silkworm Egg
minetest.register_node("petz:silkworm_eggs", {
description = S("Silkworm Eggs"),
inventory_image = "petz_silkworm_eggs_inv.png",
groups = {snappy=1, bendy=2, cracky=1, falling_node = 1},
sounds = default.node_sound_wood_defaults(),
paramtype = "light",
drawtype = "mesh",
mesh = 'petz_silkworm_eggs.b3d',
visual_scale = 1.0,
tiles = {"petz_silkworm_eggs.png"},
collision_box = {
type = "fixed",
fixed = {-0.25, -0.5, -0.062500, 0.1875, -0.4375, 0.1875},
},
selection_box = {
type = "fixed",
fixed = {-0.25, -0.5, -0.062500, 0.1875, -0.4375, 0.1875},
},
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
timer:start(math.random(200, 300))
end,
on_timer = function(pos)
if not minetest.registered_entities["petz:silkworm"] then
return
end
minetest.set_node(pos, {name= "air"})
minetest.add_entity(pos, "petz:silkworm")
local pos2 = {
x = pos.x + 1,
y = pos.y,
z = pos.z + 1,
}
if minetest.get_node(pos2) and minetest.get_node(pos2).name == "air" then
minetest.add_entity(pos2, "petz:silkworm")
end
local pos3 = {
x = pos.x - 1,
y = pos.y,
z = pos.z -1,
}
if minetest.get_node(pos3) and minetest.get_node(pos3).name == "air" then
minetest.add_entity(pos3, "petz:silkworm")
end
return false
end
})
--Spinning Wheel
minetest.register_node("petz:spinning_wheel", {
description = S("Spinning Wheel"),
groups = {snappy=1, bendy=2, cracky=1},
sounds = default.node_sound_wood_defaults(),
paramtype = "light",
drawtype = "mesh",
mesh = 'petz_spinning_wheel.b3d',
tiles = {"petz_spinning_wheel_loaded.png"},
collision_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.25, 0.5, 0.3125, 0.1875},
},
selection_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.25, 0.5, 0.3125, 0.1875},
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
meta:set_int("silk_count", 1)
meta:set_string("infotext", S("Silk Count").." = "..meta:get_int("silk_count"))
end,
on_rightclick = function(pos, node, player, itemstack, pointed_thing)
local player_name = player:get_player_name()
--minetest.chat_send_player(player_name, "name="..itemstack:get_name())
local meta = minetest.get_meta(pos)
local silk_count = meta:get_int("silk_count")
if itemstack:get_name() == "petz:cocoon" then
if silk_count == 3 then
minetest.chat_send_player(player_name, S("First, extract the silk bobbin from the spinning wheel."))
elseif silk_count == 2 then
silk_count = silk_count + 1
meta:set_int("silk_count", silk_count)
meta:set_string("infotext", S("Silk Count").." = "..tostring(silk_count))
itemstack:take_item()
minetest.chat_send_player(player_name, S("A silk bobbin has been created!"))
return itemstack
else
silk_count = silk_count + 1
meta:set_int("silk_count", silk_count)
meta:set_string("infotext", S("Silk Count").." = "..tostring(silk_count))
itemstack:take_item()
minetest.chat_send_player(player_name, S("There are still").." ".. tostring(3-silk_count).." "..S("more to create the bobbin."))
return itemstack
end
elseif silk_count == 3 then --get the bobbin
local inv = player:get_inventory()
if inv:room_for_item("main", "petz:silk_bobbin") then --firstly check for room in the inventory
local itemstack_name = itemstack:get_name()
local stack = ItemStack("petz:silk_bobbin 1")
if (itemstack_name == "petz:silk_bobbin" or itemstack_name == "") and (itemstack:get_count() < itemstack:get_stack_max()) then
itemstack:add_item(stack)
else
inv:add_item("main", stack)
end
meta:set_int("silk_count", 0) --reset the silk count
meta:set_string("infotext", S("Silk Count").." = 0")
minetest.chat_send_player(player_name, S("You got the bobbin!"))
return itemstack
else
minetest.chat_send_player(player_name, S("No room in your inventory for the silk bobbin."))
end
end
end,
})
minetest.register_craft({
type = "shaped",
output = "petz:spinning_wheel",
recipe = {
{'', 'group:wood', ''},
{'group:wood', 'petz:silk_bobbin', 'group:wood'},
{'', 'group:wood', ''},
}
})
petz.init_convert_to_chrysalis = function(self)
minetest.after(math.random(1200, 1500), function()
if not(mobkit.is_alive(self)) then
return
end
local pos = self.object:get_pos()
if minetest.get_node(pos) and minetest.get_node(pos).name ~= "air" then
return
end
minetest.set_node(pos, {name= "petz:cocoon"})
mokapi.remove_mob(self)
end, self)
end
petz.init_lay_eggs = function(self)
minetest.after(math.random(150, 240), function()
if not(mobkit.is_alive(self)) then
return
end
if self.eggs_count > 0 then
return
end
petz.alight(self, 0, "stand")
minetest.after(10.0, function()
if not(mobkit.is_alive(self)) then
return
end
local pos = self.object:get_pos()
if minetest.get_node(pos) and minetest.get_node(pos).name ~= "air" then
return
end
local node_name = petz.node_name_in(self, "below")
local spawn_egg = false
if string.sub(petz.settings.silkworm_lay_egg_on_node, 1, 5) == "group" then
local node_group = minetest.get_item_group(node_name, string.sub(petz.settings.silkworm_lay_egg_on_node, 7))
if node_group > 0 then
spawn_egg = true
end
else
if node_name == petz.settings.silkworm_lay_egg_on_node then
spawn_egg = true
end
end
if spawn_egg then
minetest.set_node(pos, {name= "petz:silkworm_eggs"})
self.eggs_count = mobkit.remember(self, "eggs_count", (self.eggs_count+1)) --increase the count of eggs
else
petz.init_lay_eggs(self) --reinit the timer, to try to lay eggs later
end
petz.ownthing(self)
end, self)
end, self)
end
--Silk
minetest.register_craftitem("petz:silk_bobbin", {
description = S("Silk Bobbin"),
inventory_image = "petz_silk_bobbin.png",
stack_max = 25,
})
minetest.register_craft({
type = "shaped",
output = 'petz:silk_bobbin',
recipe = {
{'petz:cocoon', 'default:stick', 'petz:cocoon'},
{'petz:cocoon', 'default:stick', 'petz:cocoon'},
{'petz:cocoon', 'default:stick', 'petz:cocoon'},
}
})

105
petz/petz/api/api_sleep.lua Normal file
View File

@ -0,0 +1,105 @@
petz.calculate_sleep_times = function(self)
if not petz.settings.sleeping then
return
end
if (self.sleep_at_night or self.sleep_at_day) then
local sleep_time
local sleep_start_time
local sleep_end_time
local sleep_end_time_limit
if self.sleep_at_night then
local night_start = 19500
local night_duration = 9000
sleep_time = night_duration * (self.sleep_ratio or 1)
sleep_end_time_limit = 23999 + 4500
sleep_start_time = math.random(night_start, sleep_end_time_limit - sleep_time)
sleep_end_time = sleep_start_time + sleep_time
if sleep_start_time > 23999 then
sleep_start_time = sleep_end_time_limit - sleep_start_time
end
if sleep_end_time > 23999 then
sleep_end_time = sleep_end_time - 23999
end
else
local day_start = 4500
local day_duration = 15000
sleep_time = day_duration * (self.sleep_ratio or 1)
sleep_end_time_limit = 19500
sleep_start_time = math.random(day_start, sleep_end_time_limit - sleep_time)
sleep_end_time = sleep_start_time + sleep_time
end
self.sleep_start_time = mobkit.remember(self, "sleep_start_time", sleep_start_time)
self.sleep_end_time = mobkit.remember(self, "sleep_end_time", sleep_end_time)
--minetest.chat_send_player("singleplayer", "sleep_time="..tostring(sleep_time).."/sleep_start_time="..tostring(sleep_start_time).."/sleep_end_time="..tostring(sleep_end_time))
end
end
petz.bh_sleep = function(self, prty)
if(not petz.settings.sleeping) or petz.isinliquid(self) then
return
end
--minetest.chat_send_player("singleplayer", "ana")
if (self.sleep_at_night and petz.is_night()) or (self.sleep_at_day and not(petz.is_night())) then
--minetest.chat_send_player("singleplayer", "lucas")
local timeofday = minetest.get_timeofday() * 24000
--minetest.chat_send_player("singleplayer", tostring(timeofday))
local sleep_start_time = self.sleep_start_time
local sleep_end_time = self.sleep_end_time
if self.sleep_at_night then
if timeofday > 19500 then
sleep_end_time = 23999
elseif timeofday < 4500 then
sleep_start_time = 0
end
end
--minetest.chat_send_player("singleplayer", "time of day="..tostring(timeofday).."/sleep_start_time="..tostring(self.sleep_start_time).."/sleep_end_time="..tostring(self.sleep_end_time))
if (self.status ~= "sleep") and (timeofday > sleep_start_time and timeofday < sleep_end_time) then
--minetest.chat_send_player("singleplayer", "prueba")
petz.sleep(self, prty, false)
end
end
end
petz.sleep = function(self, prty, force)
self.status = mobkit.remember(self, "status", "sleep")
mobkit.animate(self, 'sleep')
local texture = self.textures[self.texture_no]
self.object:set_properties(self, {textures = {texture.."^petz_"..self.type.."_sleep.png"}}) --sleeping eyes
petz.hq_sleep(self, prty, force)
end
function petz.hq_sleep(self, prty, force)
local timer = 2
local func=function()
timer = timer - self.dtime
if timer < 0 then
if not(force) then
local timeofday = minetest.get_timeofday() * 24000
local sleep_start_time = self.sleep_start_time
local sleep_end_time = self.sleep_end_time
if self.sleep_at_night then
if timeofday > 19500 then
sleep_end_time = 23999
elseif timeofday < 4500 then
sleep_start_time = 0
end
end
if (self.status == "sleep") and timer < 0 --check if status did not change
and (self.sleep_at_night and not(petz.is_night())) or (self.sleep_at_day and petz.is_night())
or (timeofday < sleep_start_time) or (timeofday > sleep_end_time) then
mobkit.clear_queue_high(self) --awake
local texture = self.textures[self.texture_no]
self.object:set_properties(self, {textures = {texture}}) --quit sleeping eyes
self.status = mobkit.remember(self, "status", nil)
return true
else
petz.do_particles_effect(self.object, self.object:get_pos(), "sleep")
end
else
petz.do_particles_effect(self.object, self.object:get_pos(), "sleep")
end
timer = 2
end
end
mobkit.queue_high(self,func,prty)
end

261
petz/petz/api/api_spawn.lua Normal file
View File

@ -0,0 +1,261 @@
petz.get_node_below = function(pos)
local pos_below = {
x = pos.x,
y = pos.y - 1.0,
z = pos.z,
}
local node = minetest.get_node(pos_below)
return node
end
function petz.spawn_is_in_deep(nodepos)
if not nodepos then
return false
end
nodepos.y = nodepos.y + 1.1
local node_1_above = mobkit.nodeatpos(nodepos)
nodepos.y= nodepos.y + 1
local node_2_above = mobkit.nodeatpos(nodepos)
if (node_1_above and node_1_above.drawtype == 'liquid') and (node_2_above and node_2_above.drawtype == 'liquid') then
return true
else
return false
end
end
petz.spawn_mob = function(spawn_pos, limit_max_mobs, abr, liquidflag)
if petz.settings.no_spawn_in_protected and minetest.is_protected(spawn_pos, "") then
return
end
local node
if not(liquidflag) then
node = petz.get_node_below(spawn_pos) --the node below the spawn pos
else --liquid
if not(petz.spawn_is_in_deep(spawn_pos)) then --spawn only in deep
return
else
node = minetest.get_node(spawn_pos)
end
end
--Spawn Peaceful or monsters?
local peaceful_monsters_random
if not(petz.settings.disable_monsters) then
peaceful_monsters_random = math.random()
else
peaceful_monsters_random = 0.0
end
--minetest.chat_send_player("singleplayer", tostring(peaceful_monsters_random))
local peaceful
if peaceful_monsters_random <= petz.settings.spawn_peaceful_monsters_ratio then
peaceful = true
else
peaceful = false
end
local candidates_list = {} --Create a sublist of the petz with the same node to spawnand between max_height and min_height
for i = 1, #petz.settings["petz_list"] do
local pet_name
local can_spawn = true
pet_name = petz.settings["petz_list"][i]
local mob_ent_name = "petz:"..pet_name
--minetest.chat_send_player("singleplayer", mob_ent_name)
local ent = minetest.registered_entities[mob_ent_name]
-- Note: using a function that just returns false on the first condition that is not met
-- might be easier to read than this current implementation
if ent then --do several checks to know if the mob can be included in the list or not
if can_spawn and petz.settings[pet_name.."_disable_spawn"] then
can_spawn = false
end
if can_spawn and ((ent.is_monster and peaceful) or (not(ent.is_monster) and not(peaceful))) then
can_spawn = false
end
if can_spawn and ent.spawn_max_height then --check max_height
if spawn_pos.y > ent.spawn_max_height then
can_spawn = false
end
end
if can_spawn and ent.spawn_min_height then --check min_height
if spawn_pos.y < ent.spawn_min_height then
can_spawn = false
end
end
if can_spawn and ent.min_daylight_level then --check min_light
local daylight_level = minetest.get_node_light(spawn_pos, 0.5)
if not(daylight_level) or (daylight_level < ent.min_daylight_level) then
can_spawn = false
end
end
if can_spawn and ent.max_daylight_level then --check max_light
local daylight_level = minetest.get_node_light(spawn_pos, 0.5)
if not(daylight_level) or (daylight_level > ent.max_daylight_level) then
can_spawn = false
end
end
--Check if this mob spawns at night
if can_spawn and ent.spawn_at_night then
if not(petz.is_night()) then --if not at night
can_spawn = false
end
end
--Check if monsters are disabled
if can_spawn and ent.is_monster then
if petz.settings.disable_monsters then
can_spawn = false
end
end
--Check if seasonal mobs
local season = petz.settings[pet_name.."_seasonal"]
if can_spawn and season then
local now_month = petz.get_os_month()
if season == "halloween" then
if now_month ~= 10 then
can_spawn = false
end
elseif season == "christmas" then
if now_month ~= 12 then
can_spawn = false
end
end
end
end
if can_spawn and mokapi.item_in_itemlist(node.name, petz.settings[pet_name.."_spawn_nodes"]) then
table.insert(candidates_list, pet_name)
end
end --end for
--minetest.chat_send_player("singleplayer", minetest.serialize(candidates_list))
if #candidates_list < 1 then --if no candidates, then return
return
end
local random_mob = candidates_list[math.random(1, #candidates_list)] --Get a random mob from the list of candidates
local random_mob_name = "petz:" .. random_mob
--minetest.chat_send_player("singleplayer", random_mob)
local spawn_chance = petz.settings[random_mob.."_spawn_chance"]
if spawn_chance < 0 then
spawn_chance = 0
elseif spawn_chance > 1 then
spawn_chance = 1
end
spawn_chance = math.floor((1 / spawn_chance)+0.5)
--minetest.chat_send_player("singleplayer", tostring(spawn_chance))
local random_chance = math.random(1, spawn_chance)
--minetest.chat_send_player("singleplayer", tostring(random_chance))
if random_chance == 1 then
local random_mob_biome = petz.settings[random_mob.."_spawn_biome"]
--minetest.chat_send_player("singleplayer", "biome="..random_mob_biome)
if random_mob_biome ~= "default" then --specific biome to spawn for this mob
local biome_name = minetest.get_biome_name(minetest.get_biome_data(spawn_pos).biome) --biome of the spawn pos
--minetest.chat_send_player("singleplayer", "biome="..biome_name)
if biome_name ~= random_mob_biome then
return
end
end
local mob_count = 0
if limit_max_mobs then
local objs = minetest.get_objects_inside_radius(spawn_pos, abr*16 + 5)
for _, obj in ipairs(objs) do -- count mobs in abrange
if not obj:is_player() then
local luaent = obj:get_luaentity()
if luaent then
mob_count = mob_count + 1
end
end
end
end
if not(limit_max_mobs) or (mob_count < petz.settings.max_mobs) then --check for bigger mobs:
local spawn_herd = petz.settings[random_mob.."_spawn_herd"]
if spawn_herd then
--minetest.chat_send_player("singleplayer", tonumber(spawn_herd))
if spawn_herd == 0 then
spawn_herd = 1
elseif spawn_herd > 5 then
spawn_herd = 5
end
else
spawn_herd = 1
end
for i = 1, math.random(1, spawn_herd) do
local spawn = true
if i == 2 then
spawn_pos.x = spawn_pos.x + 1
elseif i == 3 then
spawn_pos.x = spawn_pos.x - 2
elseif i == 4 then
spawn_pos.x = spawn_pos.x + 1
spawn_pos.z = spawn_pos.z + 1
else
spawn_pos.z = spawn_pos.z - 2
end
--[[
if i > 1 then
local height, liquidflag2 = mobkit.get_terrain_height(spawn_pos, 32)
if height or (liquidflag2 and ent.can_swin) then
local node_below = petz.get_node_below(spawn_pos)
if not(mokapi.item_in_itemlist(node_below.name, petz.settings[random_mob.."_spawn_nodes"])) then
spawn = false
end
end
end
]]
if spawn then
spawn_pos = petz.pos_to_spawn(random_mob_name, spawn_pos) --recalculate pos.y for bigger mobs
minetest.add_entity(spawn_pos, random_mob_name)
--minetest.chat_send_player("singleplayer", random_mob.. " spawned!!!")
end
--minetest.chat_send_player("singleplayer", "cave="..tostring(cave))
end
end
end
end
minetest.register_globalstep(function(dtime)
local abr = tonumber(minetest.get_mapgen_setting('active_block_range')) or 3
local radius = abr * 16 --recommended
local interval = petz.settings.spawn_interval
local spawn_pos, liquidflag = mobkit.get_spawn_pos_abr(dtime, interval, radius, petz.settings.spawn_chance, 0.2)
if spawn_pos then
petz.spawn_mob(spawn_pos, true, abr, liquidflag)
end
end)
-- Spawn some mobs when area loaded
--minetest.register_on_generated(function(minp, maxp, seed)
--if not(petz.settings.generated_area_create_mobs) then
--return
--end
--local debug = "minp="..(minetest.pos_to_string(minp))..", maxp="..(minetest.pos_to_string(maxp))..", seed="..seed
--minetest.chat_send_all(debug)
--local max_mobs = petz.settings.max_mobs * (petz.settings.generated_area_mob_ratio or 1)
--Get a random pos
--for i = 1, max_mobs do
--local spawn_pos = { x= math.random(minp.x, maxp.x), y = math.random(minp.y, maxp.y)+32, z = math.random(minp.z, maxp.z)}
--local height, liquidflag = mobkit.get_terrain_height(spawn_pos, 32)
--local debug = "spawn pos=".. minetest.pos_to_string(spawn_pos)
--minetest.chat_send_all(debug)
--if height then
--minetest.chat_send_all("test")
--petz.spawn_mob(spawn_pos, false)
--end
--end
--end)
petz.pos_to_spawn = function(pet_name, pos)
local x = pos.x
local y = pos.y
local z = pos.z
if minetest.registered_entities[pet_name] and minetest.registered_entities[pet_name].visual_size.x then
if minetest.registered_entities[pet_name].visual_size.x >= 32 and
minetest.registered_entities[pet_name].visual_size.x <= 48 then
y = y + 2
elseif minetest.registered_entities[pet_name].visual_size.x > 48 then
y = y + 5
else
y = y + 1
end
end
local spawn_pos = { x = x, y = y, z = z}
return spawn_pos
end

View File

@ -0,0 +1,161 @@
local S = ...
--
--Square Ball Game for the Puppy
--
function petz.spawn_square_ball(user, strength)
local pos = user:get_pos()
pos.y = pos.y + 1.5 -- camera offset
local dir = user:get_look_dir()
local yaw = user:get_look_horizontal()
local obj = minetest.add_entity(pos, "petz:ent_square_ball")
if not obj then
return
end
obj:get_luaentity().shooter_name = user:get_player_name()
obj:set_yaw(yaw - 0.5 * math.pi)
obj:set_velocity(vector.multiply(dir, strength))
return true
end
minetest.register_node("petz:square_ball", {
description = S("Square Ball (use to throw)"),
--inventory_image = "petz_square_ball.png",
tiles = {"petz_square_ball.png", "petz_square_ball.png", "petz_square_ball.png", "petz_square_ball.png",
"petz_square_ball.png", "petz_square_ball.png"},
visual_scale = 0.35,
is_ground_content = false,
groups = {wood = 1, choppy = 2, oddly_breakable_by_hand = 1, flammable = 3},
sounds = default.node_sound_wood_defaults(),
on_use = function(itemstack, user, pointed_thing)
local strength = 20
if not petz.spawn_square_ball(user, strength) then
return -- something failed
end
itemstack:take_item()
return itemstack
end,
})
minetest.register_craft({
type = "shaped",
output = 'petz:square_ball',
recipe = {
{'wool:blue', 'wool:white', 'wool:red'},
{'wool:white', 'farming:string', 'wool:white'},
{'wool:yellow', 'wool:white', 'wool:white'},
}
})
petz.attach_squareball = function(self, thing_ent, thing_ref, shooter_name)
self.object:set_properties({visual = "cube", physical = true, visual_size = {x = 0.045, y = 0.045},
textures = {"petz_square_ball.png", "petz_square_ball.png", "petz_square_ball.png", "petz_square_ball.png",
"petz_square_ball.png", "petz_square_ball.png"}, groups = {immortal = 1}, collisionbox = {-0.15, -0.15, -0.15, 0.15, 0.15, 0.15},})
self.object:set_attach(thing_ref, "head", {x=-0.0, y=0.5, z=-0.45}, {x=0, y=0, z=0})
thing_ent.square_ball_attached = true
thing_ent.attached_squared_ball = self
mobkit.remember(thing_ent, "square_ball_attached", thing_ent.square_ball_attached)
mobkit.make_sound(thing_ent, "moaning")
if shooter_name then
local player = minetest.get_player_by_name(shooter_name)
if player then
mobkit.clear_queue_low(thing_ent)
mobkit.hq_follow(thing_ent, 15, player)
self.shooter_name = "" --disable de 'on_step' event
end
end
end
minetest.register_entity("petz:ent_square_ball", {
hp_max = 4, -- possible to catch the arrow (pro skills)
physical = false, -- use Raycast
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
visual = "wielditem",
textures = {"petz:square_ball"},
visual_size = {x = 0.2, y = 0.15},
old_pos = nil,
shooter_name = "",
parent_entity = nil,
waiting_for_removal = false,
on_activate = function(self)
self.object:set_acceleration({x = 0, y = -9.81, z = 0})
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
return false
end,
on_rightclick = function(self, clicker)
if self.object:get_attach() then --if attached
local attach = self.object:get_attach()
local inv = clicker:get_inventory()
local new_stack = "petz:square_ball"
if inv:room_for_item("main", new_stack) then
inv:add_item("main", new_stack)
else
local parent_pos = attach:get_pos()
minetest.add_item(parent_pos, new_stack)
end
self.object:set_detach()
local parent_ent = attach:get_luaentity()
parent_ent.square_ball_attached = false
parent_ent.attached_squared_ball = nil
mobkit.clear_queue_low(parent_ent)
petz.ownthing(parent_ent)
self.object:remove() --remove the square ball
mobkit.clear_queue_low(parent_ent)
petz.ownthing(parent_ent)
end
end,
on_step = function(self, dtime)
if self.shooter_name == "" then
if self.object:get_attach() == nil then
self.object:remove()
end
return
end
if self.waiting_for_removal then
self.object:remove()
return
end
local pos = self.object:get_pos()
self.old_pos = self.old_pos or pos
local cast = minetest.raycast(self.old_pos, pos, true, false)
local thing = cast:next()
while thing do
if thing.type == "object" and thing.ref ~= self.object then
--minetest.chat_send_player("singleplayer", thing.type)
if not(thing.ref:is_player()) and not(thing.ref:get_player_name() == self.shooter_name) then
local thing_ent = thing.ref:get_luaentity()
if thing_ent then
--minetest.chat_send_player("singleplayer", thing_ent.type)
if (thing_ent.type == "puppy") and not(thing.ref.square_ball_attached) then
--minetest.chat_send_player("singleplayer", "test")
petz.attach_squareball(self, thing_ent, thing.ref, self.shooter_name)
return
end
end
end
elseif thing.type == "node" then
local name = minetest.get_node(thing.under).name
if minetest.registered_items[name].walkable then
local itemstack_squareball = ItemStack("petz:square_ball")
--local meta = itemstack_squareball:get_meta()
--meta:set_string("shooter_name", self.shooter_name)
minetest.item_drop(itemstack_squareball,
nil, vector.round(self.old_pos))
self.waiting_for_removal = true
self.object:remove()
return
end
end
thing = cast:next()
end
self.old_pos = pos
end,
})

View File

@ -0,0 +1,130 @@
local S = ...
--
--The Tamagochi Mode
--
-- Increase/Descrease the pet affinity
petz.calculate_affinity_change = function(rate)
if rate < 0 then --negative rates have a reduction factor
rate = rate - (rate * petz.settings.tamagochi_reduction_factor)
end
local max_affinity = 100
local affinity_change = max_affinity * rate
return affinity_change
end
petz.set_affinity = function(self, rate)
local new_affinity = petz.round(self.affinity + petz.calculate_affinity_change(rate))
--minetest.chat_send_player(self.owner, tostring(new_affinity))
if new_affinity > 100 then
new_affinity = 100
elseif new_affinity < 0 then
new_affinity = 0
end
self.affinity = mobkit.remember(self, "affinity", new_affinity)
end
--The Tamagochi Timer
petz.init_tamagochi_timer = function(self)
if petz.settings.tamagochi_mode and self.tamed and self.init_tamagochi_timer then
petz.timer(self)
return true
else
return false
end
end
--
--Tamagochi Mode Timer
--
petz.timer = function(self)
minetest.after(petz.settings.tamagochi_check_time, function()
if mobkit.is_alive(self) then
if (not(minetest.is_singleplayer())) and (petz.settings.tamagochi_check_if_player_online) then
if not minetest.player_exists(self.owner) then --if pet owner is not online
return
end
end
local pos = self.object:get_pos()
if not(pos == nil) then --important for if the pet dies
local pos_below = {
x = pos.x,
y = pos.y - 1.5,
z = pos.z,
}
local node = minetest.get_node_or_nil(pos_below)
--minetest.chat_send_player(self.owner, petz.settings.tamagochi_safe_node)
for i = 1, #petz.settings.tamagochi_safe_nodes do --loop thru all safe nodes
if node and (node.name == petz.settings.tamagochi_safe_nodes[i]) then
self.init_tamagochi_timer = true
mobkit.remember(self, "init_tamagochi_timer", self.init_tamagochi_timer)
return
end
end
else --if the pos is nil, it means that the pet died before 'minetest.after_effect'
self.init_tamagochi_timer = false
mobkit.remember(self, "init_tamagochi_timer", self.init_tamagochi_timer) --so no more timer
return
end
--Decrease health if pet has not fed
if not self.fed then
mokapi.set_health(self, -petz.settings.tamagochi_feed_hunger_rate)
petz.update_nametag(self)
if (self.hp > 0) and self.has_affinity then
petz.set_affinity(self, -petz.settings.tamagochi_feed_hunger_rate)
end
else
self.fed = false
mobkit.remember(self, "fed", self.fed) --Reset the variable
end
--If the pet has not brushed
if self.can_be_brushed then
if not(self.brushed) then
if self.has_affinity then
petz.set_affinity(self, -petz.settings.tamagochi_brush_rate)
end
else
self.brushed = false
mobkit.remember(self, "brushed", self.brushed) --Reset the variable
end
end
--If the petz is a lion had to been lashed
if self.type== "lion" then
if not self.lashed then
petz.set_affinity(self, -petz.settings.tamagochi_lashing_rate)
else
self.lashed = false
mobkit.remember(self, "lashed", self.lashed)
end
end
--If the pet starves to death
if self.hp <= 0 then
minetest.chat_send_player(self.owner, S("Your").. " "..self.type.." "..S("has starved to death!!!"))
self.init_tamagochi_timer = false -- no more timing
--If the pet get bored of you
elseif self.has_affinity and (self.affinity == 0) then
local msg = S("Your").." "..self.type.." "..S("has abandoned you!!!")
petz.abandon_pet(self, msg)
else --else reinit the timer, to check again in the future
self.init_tamagochi_timer = true
end
end
end, self)
self.init_tamagochi_timer = false --the timer is reinited in the minetest.after function
end
petz.abandon_pet = function(self, msg)
if msg then
minetest.chat_send_player(self.owner, msg)
end
petz.delete_nametag(self)
mokapi.remove_owner(self) --the pet abandon you
petz.remove_tamed_by_owner(self, true)
petz.drop_dreamcatcher(self)
self.init_tamagochi_timer = false -- no more timing
self.for_sale = false -- not for sale
end

150
petz/petz/api/api_throw.lua Normal file
View File

@ -0,0 +1,150 @@
--effects can be: fire
function petz.throw(self, dtime, damage, effect, particles, sound)
if self.shooter_name == "" then
if self.object:get_attach() == nil then
self.object:remove()
end
return
end
if self.waiting_for_removal then
self.object:remove()
return
end
local pos = self.object:get_pos()
self.old_pos = self.old_pos or pos
local cast = minetest.raycast(self.old_pos, pos, true, false)
local thing = cast:next()
while thing do
if thing.type == "object" and thing.ref ~= self.object then
--minetest.chat_send_player("singleplayer", thing.type)
local thing_ent = thing.ref:get_luaentity()
if not(thing.ref:is_player()) or (thing.ref:is_player() and not(thing.ref:get_player_name() == self.shooter_name)) then
local ent_pos
if thing.ref:is_player() then
thing.ref:punch(thing.ref, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy=damage}}, nil)
ent_pos = thing.ref:get_pos()
if sound then
mokapi.make_sound("player", thing.ref, sound, petz.settings.max_hear_distance)
end
else
mobkit.hurt(thing_ent, damage)
ent_pos = thing.ref:get_pos()
if sound then
mokapi.make_sound("object", thing.ref, sound, petz.settings.max_hear_distance)
end
end
if effect then
if effect == "cobweb" then
minetest.set_node(ent_pos, {name = "petz:cobweb"})
end
end
if particles then
petz.do_particles_effect(nil, pos, particles)
end
self.waiting_for_removal = true
self.object:remove()
return
end
elseif thing.type == "node" then
local node_pos = thing.above
local node = minetest.get_node(node_pos)
local node_name = node.name
--minetest.chat_send_player("singleplayer", node.name)
if minetest.registered_items[node_name].walkable and minetest.registered_items[node_name] ~= "air" then
if effect then
if effect == "fire" then
local pos_above = {
x = node_pos.x,
y = node_pos.y +1,
z = node_pos.z,
}
local node_above = minetest.get_node(pos_above)
if minetest.get_item_group(node_name, "flammable") > 1
and not minetest.is_protected(node_pos, "") then
minetest.set_node(node_pos, {name = "fire:basic_flame"})
end
if node_above.name == "air" then
--if minetest.get_node(pos_above).name == "air" then
petz.do_particles_effect(nil, pos_above, "fire")
--end
end
mokapi.make_sound("pos", node_pos, "petz_firecracker", petz.settings.max_hear_distance)
elseif effect == "cobweb" then
local pos_above = {
x = node_pos.x,
y = node_pos.y +1,
z = node_pos.z,
}
local node_above = minetest.get_node(pos_above)
if node_above.name == "air" then
minetest.set_node(pos_above, {name = "petz:cobweb"})
end
end
end
self.waiting_for_removal = true
self.object:remove()
return
end
end
thing = cast:next()
end
self.old_pos = pos
end
function petz.spawn_throw_object(user, strength, entity)
local pos = user:get_pos()
if user:is_player() then
pos.y = pos.y + 1.5 -- camera offset
end
--minetest.chat_send_player("singleplayer", tostring(pos))
local obj = minetest.add_entity(pos, entity)
if not obj then
return
end
local dir
local yaw
local user_name
if user:is_player() then
yaw = user:get_look_horizontal()
dir = user:get_look_dir()
user_name = user:get_player_name()
else
yaw = user:get_yaw()
dir = minetest.yaw_to_dir(yaw)
user_name = user:get_luaentity().type
end
--minetest.chat_send_player("singleplayer", "test")
obj:get_luaentity().shooter_name = user_name
obj:set_yaw(yaw - 0.5 * math.pi)
obj:set_velocity(vector.multiply(dir, strength))
return true
end
function petz.register_throw_entity(name, textures, damage, effect, particles, sound)
minetest.register_entity(name, {
hp_max = 4, -- possible to catch the arrow (pro skills)
physical = false, -- use Raycast
collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
visual = "wielditem",
textures = {textures},
visual_size = {x = 1.0, y = 1.0},
old_pos = nil,
shooter_name = "",
parent_entity = nil,
waiting_for_removal = false,
on_activate = function(self)
self.object:set_acceleration({x = 0, y = -9.81, z = 0})
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
return false
end,
on_step = function(self, dtime)
petz.throw(self, dtime, damage, effect, particles, sound)
end,
})
end

View File

@ -0,0 +1,24 @@
--
--Wagon API
--
petz.put_wagon = function(self, clicker)
if self.wagon then --already a put wagon
return
end
local pos = self.object:get_pos()
local rotation = self.object:get_rotation()
local wagon_obj = minetest.add_entity(pos, "petz:wagon", nil)
wagon_obj:set_attach(self.object, "", {x = 0, y = 0.0, z = 0}, rotation)
mokapi.make_sound("object", self.object, "petz_pop_sound", petz.settings.max_hear_distance)
wagon_obj:set_properties({
visual_size = {
x =1,
y = 1,
},
})
self.wagon = wagon_obj
local wielded_item = clicker:get_wielded_item()
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
end

View File

@ -0,0 +1,95 @@
local S = ...
-- Whistle Item
minetest.register_craftitem("petz:whistle", {
description = S("Pet Whistle"),
inventory_image = "petz_whistle.png",
groups = {},
on_use = function (itemstack, user, pointed_thing)
local user_name = user:get_player_name()
local user_pos = user:get_pos()
minetest.show_formspec(user_name, "petz:form_whistle", petz.create_form_list_by_owner(user_name, user_pos))
end,
})
minetest.register_craft({
type = "shaped",
output = 'petz:whistle',
recipe = {
{'', '', ''},
{'', 'petz:ducky_feather', ''},
{'', 'default:steel_ingot', ''},
}
})
petz.create_form_list_by_owner = function(user_name, user_pos)
--Get the values of the list
local item_list_table = petz.tamed_by_owner[user_name]
if item_list_table then
if #item_list_table <= 0 then
minetest.chat_send_player(user_name, "You have no pets with a name to call.")
return ''
end
local item_list = ""
for key, pet_table in ipairs(item_list_table) do
local pet = pet_table.pet
if mobkit.is_alive(pet) and not(petz.str_is_empty(pet.tag)) then -- check if alive
local pet_type = pet.type:gsub("^%l", string.upper)
local pet_pos = pet.object:get_pos()
local distance, pet_pos_x, pet_pos_y, pet_pos_z
if pet_pos then
distance = tostring(petz.round(vector.distance(user_pos, pet_pos)))
pet_pos_x = tostring(math.floor(pet_pos.x+0.5))
pet_pos_y = tostring(math.floor(pet_pos.y+0.5))
pet_pos_z = tostring(math.floor(pet_pos.z+0.5))
else
pet_pos_x = "X"
pet_pos_y = "Y"
pet_pos_z = "Z"
distance = "too far away"
end
item_list = item_list .. minetest.colorize("#EE0", pet.tag).." | " .. S(pet_type) .. " | ".. "Pos = (".. pet_pos_x .. "/"
.. pet_pos_y .. "/".. pet_pos_z ..") | Dist= "..distance..","
end
end
local form_list_by_owner =
"size[6,8;]"..
"image[2,0;1,1;petz_whistle.png]"..
"textlist[0,1;5,6;petz_list;"..item_list..";selected idx]"..
"button_exit[2,7;1,1;btn_exit;"..S("Close").."]"
return form_list_by_owner
else
return ''
end
end
--On receive fields
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "petz:form_whistle" then
return false
end
if fields.petz_list then
local player_name = player:get_player_name()
local event = minetest.explode_textlist_event(fields.petz_list)
local pet_index = event.index
if not petz.tamed_by_owner[player_name][pet_index] then
return
end
local pet = petz.tamed_by_owner[player_name][pet_index].pet
--minetest.chat_send_player("singleplayer", "test1")
if pet then
--minetest.chat_send_player("singleplayer", "test2")
local pos_front_player = petz.pos_front_player(player)
local pet_pos = {
x = pos_front_player.x,
y = pos_front_player.y + 1,
z = pos_front_player.z,
}
pet.object:set_pos(pet_pos)
minetest.close_formspec(player_name, "petz:form_whistle")
mokapi.make_sound("player", player, "petz_whistle", petz.settings.max_hear_distance)
end
end
return true
end)

View File

@ -0,0 +1,101 @@
---
---Refill lamb or milk
---
local S = ...
petz.refill = function(self)
if self.type == "lamb" then
petz.lamb_wool_regrow(self)
elseif self.milkable then
petz.milk_refill(self)
end
end
--
--Lamb Wool
--
petz.lamb_wool_regrow = function(self)
if not self.shaved then --only count if the lamb is shaved
return
end
local food_count_wool = self.food_count_wool + 1
self.food_count_wool = mobkit.remember(self, "food_count_wool", food_count_wool)
if self.food_count_wool >= 5 then -- if lamb replaces 5x grass then it regrows wool
self.food_count_wool = mobkit.remember(self, "food_count_wool", 0)
self.shaved = mobkit.remember(self, "shaved", false)
local lamb_texture = "petz_lamb_"..self.skin_colors[self.texture_no]..".png"
petz.set_properties(self, {textures = {lamb_texture}})
end
end
petz.lamb_wool_shave = function(self, clicker)
local inv = clicker:get_inventory()
local color
if not(self.colorized) then
color = self.skin_colors[self.texture_no]
else
color = self.colorized
self.colorized = mobkit.remember(self, "colorized", nil) --reset the color
end
local new_stack = "wool:".. color
if inv:room_for_item("main", new_stack) then
inv:add_item("main", new_stack)
else
minetest.add_item(self.object:get_pos(), new_stack)
end
mokapi.make_sound("object", self.object, "petz_lamb_moaning", petz.settings.max_hear_distance)
local lamb_texture = "petz_lamb_shaved_"..self.skin_colors[self.texture_no]..".png"
petz.set_properties(self, {textures = {lamb_texture}})
self.shaved = mobkit.remember(self, "shaved", true)
self.food_count_wool = mobkit.remember(self, "food_count_wool", 0)
petz.bh_afraid(self, clicker:get_pos())
mokapi.make_sound("object", self.object, "petz_pop_sound", petz.settings.max_hear_distance)
end
---
--Calf Milk
---
petz.milk_refill = function(self)
self.food_count = self.food_count + 1
mobkit.remember(self, "food_count", self.food_count)
if self.food_count >= 5 then -- if calf replaces 5x grass then it refill milk
self.food_count = mobkit.remember(self, "food_count", self.food_count)
self.milked = mobkit.remember(self, "milked", false)
end
end
petz.milk_milk = function(self, clicker)
if self.is_male then
minetest.chat_send_player(clicker:get_player_name(), S("Milk only female animals!"))
return
end
local inv = clicker:get_inventory()
local wielded_item = clicker:get_wielded_item()
wielded_item:take_item()
clicker:set_wielded_item(wielded_item)
if inv:room_for_item("main", "petz:bucket_milk") then
inv:add_item("main","petz:bucket_milk")
mokapi.make_sound("object", self.object, "petz_"..self.type.."_moaning", petz.settings.max_hear_distance)
else
minetest.add_item(self.object:get_pos(), "petz:bucket_milk")
end
self.milked = mobkit.remember(self, "milked", true)
end
---
--Cut a feather
---
petz.cut_feather = function(self, clicker)
local inv = clicker:get_inventory()
local item_stack= "petz:ducky_feather"
if inv:room_for_item("main", item_stack) then
inv:add_item("main", item_stack)
else
minetest.add_item(self.object:get_pos(), item_stack)
end
mokapi.make_sound("object", self.object, "petz_"..self.type.."_moaning", petz.settings.max_hear_distance)
petz.bh_afraid(self, clicker:get_pos())
end

15
petz/petz/awards.lua Normal file
View File

@ -0,0 +1,15 @@
awards.register_trigger("milk", {
type = "custom",
progress = "@1/@2 buckets of milk",
auto_description = { "Do a foo", "Foo @1 times" },
})
--minetest.register_on_milk(function()
--for _, trigger in pairs(awards.on.milk) do
--if condition then
--awards.unlock(trigger)
--end
--end
--end)

1
petz/petz/docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_site

View File

@ -0,0 +1 @@
I"ð{"source"=>"/opt/minetest/games/bogart/mods/petz/petz/docs", "destination"=>"/opt/minetest/games/bogart/mods/petz/petz/docs/_site", "collections_dir"=>"", "cache_dir"=>".jekyll-cache", "plugins_dir"=>"_plugins", "layouts_dir"=>"_layouts", "data_dir"=>"_data", "includes_dir"=>"_includes", "collections"=>{"posts"=>{"output"=>true, "permalink"=>"/:categories/:year/:month/:day/:title:output_ext"}}, "safe"=>false, "include"=>[".htaccess"], "exclude"=>["README.md", ".sass-cache", ".jekyll-cache", "gemfiles", "Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"], "keep_files"=>[".git", ".svn"], "encoding"=>"utf-8", "markdown_ext"=>"markdown,mkdown,mkdn,mkd,md", "strict_front_matter"=>false, "show_drafts"=>nil, "limit_posts"=>0, "future"=>false, "unpublished"=>false, "whitelist"=>[], "plugins"=>[], "markdown"=>"kramdown", "highlighter"=>"rouge", "lsi"=>false, "excerpt_separator"=>"\n\n", "incremental"=>false, "detach"=>false, "port"=>"4000", "host"=>"127.0.0.1", "baseurl"=>"", "show_dir_listing"=>false, "permalink"=>"date", "paginate_path"=>"/page:num", "timezone"=>nil, "quiet"=>false, "verbose"=>false, "defaults"=>[], "liquid"=>{"error_mode"=>"warn", "strict_filters"=>false, "strict_variables"=>false}, "kramdown"=>{"auto_ids"=>true, "toc_levels"=>"1..6", "entity_output"=>"as_char", "smart_quotes"=>"lsquo,rsquo,ldquo,rdquo", "input"=>"GFM", "hard_wrap"=>false, "guess_lang"=>true, "footnote_nr"=>1, "show_warnings"=>false}, "title"=>"Bogart Game", "tag_text"=>"Bogart Game", "description"=>"A responsive template for publishing single-page websites, articles that are easy on the eyes", "url"=>"http://localhost:4000", "font-awesome-include"=>true, "livereload_port"=>35729, "serving"=>true, "watch"=>true}:ET

View File

@ -0,0 +1,543 @@
I"­b<p><img src="images/petz_logo.png" alt="Logo" /></p>
<p><img src="images/petz_items.png" alt="Items" /></p>
<p>Are you tired of ugly mobs? Do you like the kawaii world and taste?
The PetZ are here now for you!</p>
<h3 id="mobs">Mobs</h3>
<h4 id="kitty">Kitty</h4>
<p><img src="images/kitty.png" alt="Kitty" /></p>
<ul>
<li>It avaliable in 6 colors.</li>
</ul>
<h4 id="puppy">Puppy</h4>
<p><img src="images/puppy.png" alt="Puppy" /></p>
<ul>
<li>3 colors.</li>
</ul>
<h4 id="duckies">Duckies</h4>
<p><img src="images/ducky.png" alt="Ducky" /></p>
<ul>
<li>Three types: Yellow, Black and Mallard.</li>
<li>Peaceful and dumb animal.</li>
<li>They can put duck eggs from time to time.You can tame it but not give it any order.</li>
<li>You can breed ducks creating a nest with an egg inside, optionally you can leave an empty nest near a ducky so it lay an egg.</li>
<li>It drops feathers when killed.</li>
<li>You can fry the eggs.</li>
<li>Fried egg and bacon: A fried egg plus a porkchop.</li>
</ul>
<h4 id="beaver">Beaver</h4>
<p><img src="images/beaver.png" alt="Beaver" />
Behaviour:</p>
<ul>
<li>It lives near water (in rivers in the case of valleys mapgen).</li>
<li>It can be tamed.</li>
<li>It can walk, swim and dive underwater.</li>
<li>It drops Beaver Fur to create Beaver Oil when killed.</li>
<li>It got a chance of create an unique dam on the coast or river.</li>
<li>You can spread beaver oil on your pet skin. In tamagochi mode your pet will be happy, but the fact of not do it it is not mandatory for it to be sad.</li>
</ul>
<h4 id="lamb">Lamb</h4>
<p><img src="images/lamb.png" alt="Lamb" />
In 3 colors: White (common), grey &amp; dark gray (rare) and brown (very rare).</p>
<ul>
<li>Lambs eat grass.</li>
<li>You can get Wool with the Shears (right click).</li>
<li>To wool to regrow feed your lamb or let it eats grass.</li>
<li>Lambs runaway from player, tame them with some wheat.</li>
<li>Predators: Wolf &amp; Lion.</li>
</ul>
<h4 id="lion">Lion</h4>
<p><img src="images/lion.png" alt="Lion" /></p>
<ul>
<li>It lives in the Savanna. Wild animal. Dangerous.</li>
<li>It likes raw meat.</li>
<li>Can be tamed and give it orders with meat or a Whip (3 lashings to tame)
In Tamagochi Mode:</li>
<li>You have to lash your lion in 48h or it lost affinitty with you.</li>
<li>Be careful, if you lost your lion as pet, it will attack you!</li>
<li>Preys: Lambs, piggies and ponies.</li>
</ul>
<h4 id="calf">Calf</h4>
<p><img src="images/calf.png" alt="Calf" /></p>
<ul>
<li>Available in three skins.</li>
<li>It eats grass from time to time, like the lambs.</li>
<li>It drops Leather when killed.</li>
<li>It can be milked with an empty bucket.</li>
<li>In order the calf to have more milk, you have to feed it or let it to eat some grass.</li>
<li>Milk is drinkable.</li>
<li>Put a bucket of milk in the oven to get Cheese.</li>
<li>Predators: Calf.</li>
</ul>
<h4 id="panda">Panda</h4>
<p><img src="images/panda.png" alt="Panda" /></p>
<ul>
<li>Panda is tamable and loves papyrus.</li>
</ul>
<h4 id="frog">Frog</h4>
<p><img src="images/frog.png" alt="Frog" /></p>
<ul>
<li>Frog is a semiaquatic animal. It loves fireflies to eat’em. It drops a leg that you can cook in order to get a Roasted Frog Leg (food).</li>
</ul>
<h4 id="grizzly">Grizzly</h4>
<p><img src="images/grizzly.png" alt="Grizzly" /></p>
<ul>
<li>Not a Teddy Bear, but a wild one. It lives in woods. It’s tamable like the lion.</li>
<li>Preys: Lamb.</li>
</ul>
<h4 id="pony">Pony</h4>
<p><img src="images/pony.png" alt="Pony" /></p>
<ul>
<li>You can mount it with a Saddle and get a ride.</li>
<li>You can give it orders.</li>
<li>The Saddle can be cut with the Shears.</li>
<li>Ponies are slow where you ride them. You can breeding them to get stronger and fastest ones.</li>
<li>Predators: Lion.</li>
</ul>
<h4 id="parrot">Parrot</h4>
<p><img src="images/parrot.png" alt="Parrot" /></p>
<ul>
<li>Five species.</li>
<li>Tamable and you can give it orders.</li>
<li>It loves wheat seeds.</li>
<li>It lives naturally in the jungle.</li>
<li>You can order it to alight and to fly again.</li>
<li>It can drop Raw Parrot meat which it can be cooked.</li>
<li>You can put your parrot on your shoulder (2 minutes max.).</li>
<li>You can put your parrot on a Bird Stand.</li>
</ul>
<h4 id="chicken">Chicken</h4>
<p><img src="images/chicken.png" alt="Chicken" /></p>
<ul>
<li>Farm Animal.</li>
<li>It can lay Chicken Eggs like the duckies.</li>
<li>It drops Raw Chicken to cook it as food.</li>
<li>Get Chicken Legs with Raw Chichen.</li>
<li>Put a lot of Roasted Chicken Legs into a bucket, to get a super-delicious bucket of Chicken Legs.</li>
</ul>
<h4 id="pigeon">Pigeon</h4>
<p><img src="images/pigeon.png" alt="Pigeon" /></p>
<ul>
<li>Flying bird.</li>
</ul>
<h4 id="chimp">Chimp</h4>
<p><img src="images/chimp.png" alt="Chimp" /></p>
<ul>
<li>Agile monkey.</li>
<li>Arboreal mob: It can climb trees, wood and leaves.</li>
<li>It loves blueberries.</li>
</ul>
<h4 id="piggy">Piggy</h4>
<p><img src="images/piggy.png" alt="Piggy" /></p>
<ul>
<li>It’s a source of meat.</li>
<li>It drops Porkchop to being cooked.</li>
<li>Predators: Lion.</li>
</ul>
<h4 id="turtle">Turtle</h4>
<p><img src="images/turtle.png" alt="Turtle" /></p>
<ul>
<li>Semiaquatic mob.</li>
<li>It eats kelps.</li>
<li>It has a chance of drop its shell.</li>
</ul>
<h4 id="fishes">Fishes</h4>
<p><img src="images/clownfish.png" alt="Clownfish" />
<img src="images/tropicalfish.png" alt="Tropical Fish" />
Clownfish &amp; Tropical Fish</p>
<ul>
<li>It lives close to a coral reef.</li>
<li>It loves orange coral (clownfish) or brown coral (tropical fish).</li>
<li>It can be captured and put into a fish tank.</li>
<li>It suffocates when outside water.</li>
<li>In tamagochi mode you have only to feed it, but no if it is in a fish tank.</li>
</ul>
<h4 id="wolf">Wolf</h4>
<p><img src="images/wolf.png" alt="Wolf" /></p>
<ul>
<li>Wild animal.</li>
<li>Run away from players til players attack them, then agressive.</li>
<li>Tamable in the same way as lion.</li>
<li>Preys: Lambs.</li>
<li>Wolves can be turned into puppies: Tame the wolf with a whip, then feed it with bones (until 5, configurable in petz.conf).</li>
</ul>
<h4 id="moth">Moth</h4>
<p><img src="images/chimp.png" alt="Moth" /></p>
<ul>
<li>It spawns only at night in the coniferous forest.</li>
<li>It dies when daylight comes, unless it would be in a dark place for protection, i.e. a cave or a closed box. It needs some obscurity, not a totally dark place.</li>
<li>A moth can be captured with an empty glass bottle. Deco item. If you break the bottle, the moth liberates.</li>
</ul>
<h4 id="silkworm">Silkworm</h4>
<p><img src="images/silkworm.png" alt="Silkworm" /></p>
<ul>
<li>It spawn naturally on coniferous forests.</li>
<li>It eats all kind of leaves.</li>
<li>You can produce Silk (see below).</li>
</ul>
<h4 id="camel">Camel</h4>
<p><img src="images/camel.png" alt="Camel" /></p>
<ul>
<li>It lives in deserts.</li>
<li>It eats dry shrub.</li>
<li>Predator: Lion</li>
<li>Milkable.</li>
<li>You can breed them. Baby camels. Genetics. Mutation: White Camel.</li>
<li>Mountable with a saddle; Get a ride in the desert!</li>
<li>You can put a Saddlebag on it (right click): You gain access to the Saddlebag Inventory (16 items máx.), in the form -&gt; click on the icon of the Saddlebag.</li>
<li>Each camel has its own separated saddlebag inventory.</li>
<li>The inventory of the saddlebag is permanent. You got it even after server restarts.</li>
<li>If the camel died, the inventory of the saddlebag will drop.</li>
<li>If you captured a camel, the saddlebag with the inventory too.</li>
<li>You can put together the saddle and the saddlebag. But on right click you will mount it. To access to the inventory of the saddlebag use the shears to quit both items. Then put a saddlebag only.</li>
</ul>
<h4 id="bat">Bat</h4>
<p><img src="images/bat.png" alt="Bat" /></p>
<ul>
<li>Spawn in interiors (caves)</li>
<li>If spawned outside, only at night, and when sunrise dies.</li>
<li>It eats and follows fireflies.</li>
</ul>
<h4 id="hamster">Hamster</h4>
<p><img src="images/hamster.png" alt="Hamster" /></p>
<ul>
<li>It lives in deserts.</li>
<li>6 colors.</li>
<li>Breed them.</li>
<li>Mutation: Pink Hamster.</li>
</ul>
<h4 id="dolphin">Dolphin</h4>
<p><img src="images/dolphin.png" alt="Dolphin" /></p>
<ul>
<li>It lives in oceans.</li>
</ul>
<h4 id="toucan">Toucan</h4>
<p><img src="images/toucan.png" alt="Toucan" />
-It lives in the jungle.
-It eats apples.
-Tamable. You can put it in a bird stand.</p>
<h4 id="bee">Bee</h4>
<p><img src="images/bee.png" alt="Bee" /></p>
<ul>
<li>Flying insect.</li>
<li>It lives in behives and stays close to them.</li>
<li>It produces honey. It searches for flowers to get the pollen and then return to the behive.</li>
<li>Two types: Queen and workers (normal).</li>
<li>All the bees return to their behive at night and go out at the morning, except the Queen Bee that can fly 24 hours.</li>
<li>All the bees need belong to a behive. If their behive is destroyed, all the bees will die. Only the Queen Bees do not need a behive to survive.</li>
<li>Worker Bees do not spawn naturally.</li>
<li>Queen Bees can spawn and create one colony (behive) in wood or leaves.</li>
<li>Bees can drop pollen and/or a sting.</li>
</ul>
<h3 id="things-you-can-with-petz">Things you can with Petz</h3>
<ul>
<li>Configure the models as “meshâ€<C3A2> (by default) or “cubicâ€<C3A2> (nodebox, no animated, no too laggy) via the ‘petz.conf’</li>
<li>Configure the mob API: Only “mobs_redoâ€<C3A2> by now via ‘petz.conf’.</li>
<li>Configure the following food (aka food to health) it via ‘petz.conf’. Use right click.</li>
<li>Give it orders: follow you or stand: Right click if you are the owner.</li>
<li>Configure if they spawn in the map via ‘petz.conf’.</li>
<li>Your pet can be tamed and captured.</li>
<li>Internationalization support.</li>
<li>Spawn Eggs.</li>
</ul>
<p>NodeboxEditor (.nbe) and Blender (.blend) models included.</p>
<h3 id="licenses">Licenses</h3>
<ul>
<li>Models, icons and textures by runs. GPL3 Feel free to use it.</li>
<li>Sounds: Check the ‘license.md’ file inside the ‘sounds’ folder.</li>
</ul>
<h3 id="depends">Depends</h3>
<p>default, mobs, stairs, dye, vessels, wool</p>
<h3 id="optional">Optional</h3>
<p>bonemeal</p>
<h3 id="tamagochi-mode">Tamagochi Mode</h3>
<p>If this mode is activated (true by default) you have to take care of your pet. The pet will have two stats: Love and Hunger. If those stats go down to 0, your pet abandon you or will starve.</p>
<p>In multiplayer games (servers) the Tamagochi Mode is paused if the pet owner is offline.</p>
<h4 id="feed-it">Feed it!</h4>
<p>-You have to feed your pet once each 2 days at least (Minetest time) (right click wielding its food) (the food is configurable via petz.conf). Your pet then would be happy. Check your pet status (right click), if “Hungryâ€<C3A2> feed it, but if ‘Satiated’ then don’t bother. If you do not feed your pet every 48 hours, its health would damaged and it would be sad.
This does not apply if your pet is inside its kennel.</p>
<h4 id="brush-it">Brush it!</h4>
<p><img src="images/brush.png" alt="Brush" />
You have to brush your pet once each 2 days at least, or it will be sad. Firstly create a hairbrush with two wood sticks and one string.
This does not apply if your pet is inside its kennel.</p>
<h4 id="lash-it">Lash it!</h4>
<p><img src="images/lash.png" alt="Lash" />
In the case of a lion or grizzly, you have to lash it with a whip once each 2 days at least in order to control it.
Do not use the whip with another petz!</p>
<h4 id="polish-it">Polish it!</h4>
<p><img src="images/beaver_oil.png" alt="Beaver Oil" />
You can spread beaver oil on your pet skin. In tamagochi mode your pet will be happy, but the fact of not do it it is not mandatory for it to be sad.</p>
<p>Also keep in mind that:</p>
<ul>
<li>If you don’t feed your pet in 8 days will die (configurable).</li>
<li>If you punch your pet, it gets unhappy.</li>
<li>If your pet is unhappy, it could abandon you.</li>
<li>If your pet is inside its kennel, it’ll be well cared for and happy and won’t starve. But close the door!</li>
</ul>
<p>Notes</p>
<ul>
<li>You can configure the time when your pet is checked in ‘pet.conf’. 2400 by default (2 days).</li>
<li>In a singleplayer game the pet stats remain intact between restarts.</li>
<li>You can configure the node over where your pet is safe (no hunger) in ‘pet.conf’. So you can do your our kennels.</li>
<li>The Tamagochi Mode is paused for pet owners in multiplayer games (servers) when they are offline.</li>
</ul>
<h3 id="pet-bowl">Pet Bowl</h3>
<p><img src="images/pet_bowl.png" alt="Pet Bowl" />
Make a house to your pet and put a Pet Bowl. The pet will stand near it.</p>
<h3 id="kennel">Kennel</h3>
<p><img src="images/kennel.png" alt="Kennel" />
A schematic. Simply make a hole and punch inside it. You can put your pet inside after capture it. For creative mode only.
In there your dog will be well cared for and you won’t have to worry about its health.</p>
<h3 id="duckschicken-farm">Ducks/Chicken Farm</h3>
<p><img src="images/duck_chicken_farm.png" alt="Ducks/Chicken Farm" />
You can breed ducks or chickens via its eggs:</p>
<ul>
<li>Create a empty nest and put an egg inside (right click), optionally you can create a nest with an already egg inside. Await for the egg to hatch into a new ducky or chicken.</li>
<li>Also if a ducky or chicken has an empty nest near, it can lay an egg on it.</li>
<li>You can extract the egg from a nest (right-click on the nest).</li>
</ul>
<h3 id="capture-petz">Capture Petz</h3>
<p>Use the followig items to capture a petz:</p>
<ul>
<li>MobsRedo Net and Default Bug Net for Frog, Chicken, Kitty, Parrot, Pigeon, Ducky, Beaver, Clownfish, Monkey and Turtle.</li>
<li>MobsRedo Lasso for Calf, Lion, Puppy, Piggy, Lamb, Panda, Grizzly and Pony.</li>
</ul>
<h3 id="capture-mechanics">Capture Mechanics:</h3>
<ul>
<li>To capture a pet (i.e. kitty) you have to own it. But to to capture a no pet (i.e. frog) you can capture it directely.</li>
<li>To own a pet you have to tame it.</li>
<li>To tame a pet you have to feed it with its favourite food 5 times. Or lash it in the case of the lion and grizzly.</li>
<li>You cannot capture the pets of other players by default. To allow to rob pets change the setting ‘rob_mobs’ in ‘petz.confâ€<C3A2> file.</li>
</ul>
<h3 id="beaver-dam">Beaver Dam</h3>
<p><img src="images/beaver_dam.png" alt="Beaver Dam" />
The beaver’s home</p>
<h3 id="fish-tank">Fish Tank</h3>
<p><img src="images/fish_tank.png" alt="Fish Tank" /></p>
<ul>
<li>Put your fish inside (right-click)</li>
<li>Recover your fish with the Bug Net (right click) or breaking it.</li>
<li>You can connect several fish tank nodes to build bigger tanks and add more fishes (one by node).</li>
</ul>
<h3 id="ponycamel-breeding">Pony/camel Breeding</h3>
<p><img src="images/baby_pony.png" alt="Baby Pony" /><img src="images/pony_breeding.png" alt="Pony Breeding" /></p>
<ul>
<li>Ponies/camels can be male or female. Check its gender right clicking on them.</li>
<li>Each animal has its own velocity forward, velocity backward and acceleration. You can read its characteristics with the format “1/1/1â€<C3A2> where the numbers represent these 3 characteristics.</li>
<li>Create a Glass Syringe.</li>
<li>Use (right-click) the syringe on a male animal to get its germ.</li>
<li>Use (right-click) the syringe with germ on a female animal. The animal will be pregnant.</li>
<li>Right click on a pregnant female animal to check its pregnancy status.</li>
<li>After 2 days (configurable) a little baby will born with a mixture of gens, from its father and its mother.</li>
<li>Baby ponies/camels cannot be ridered.</li>
<li>After 2 days (configurable) the baby will get to adult.</li>
<li>You should select the best parent ponies to get better descendency (fastest ponies/camels) when breeding.</li>
<li>You can breed any animal even if you do not own it. But the owner of the babies will be the mother’s owner.</li>
<li>The male germ is unlimited but a female pony/camel only can give birth 5 babies máx. After those 5 babies, the mommy turn into infertile.</li>
</ul>
<h4 id="the-method-of-breeding">The method of breeding</h4>
<ul>
<li>1/2/3 means a velocity of 1 for forward, 2 for backward and 3 is the acceleration. So the first number of the triad is the most important.</li>
<li>Naturally spawned ponies/camels have speed statistics from 1/1/1 to 4/4/4. This means that spawned ponies/camels are slow animals (40% of the speed limit in the best case).</li>
<li>The hypothetical faster pony would be a 10/10/10. You have to breed the natural ponies/camels to achieve faster ones.</li>
<li>Keep in mind that even fast parents can procreate a slow child. So you’ll have to breed several times to get an optimal child.</li>
<li>The method is to breed parents with high speed statistics to get the best descendants, then select the fastest descendants to continue breeding them. This is a very slow process. Be patient.</li>
</ul>
<h3 id="square-ball">Square Ball</h3>
<p><img src="images/squareball.png" alt="Square Ball" /></p>
<ul>
<li>Make a Square Ball.</li>
<li>Throw it to your puppy. You have to hit the target.</li>
<li>Your puppy bring back the square ball to you.</li>
<li>To get the ball, right click on it.</li>
</ul>
<h3 id="recipes">Recipes</h3>
<p><img src="images/recipes.png" alt="Recipes" /></p>
<ul>
<li>Blueberry Cheese Cake = Blueberries, wheat, cheese and egg.</li>
<li>Blueberry Ice Cream: Blueberries, wheat, milk, 2 eggs and 2 snows = 3 ice creams.</li>
<li>Blueberry Muffin: Blueberries, 2 wheat, milk, 2 eggs and paper = 8 muffins.</li>
</ul>
<h3 id="lamb-hamster-panda-and-elephant-breed">Lamb, Hamster, Panda and Elephant Breed</h3>
<p>You can get baby lambs, hamsters and elefants.
1) Those petz could be male/female. Right-click on them to check its gender.
2) Get blueberries. (configurable in petz.conf)
3) Use (right-click) blueberries with the petz to heat them.
4) When a rut male petz found a oestrus female (close), she get pregnant.
5) Affer one day a baby will born.
6) Genetics: The baby will inherit the color from its parents. From dominant to recessive genes: white, gray, dark gray and brown in the case of lambs. This means: white color is the most common, parents both white could have a child of any color, if both brown all their descendants will be brown, etc.
6) The little petz will grown in one day.</p>
<h4 id="mutation-vanilla-lamb--white-elephant">Mutation! Vanilla lamb | White Elephant!</h4>
<p><img src="images/mutation.png" alt="Mutation" />
Also petz can suffer from a very rare mutation in its genes when spawn or breed, in a 1:200 ratio.</p>
<ul>
<li>You can get a Vanilla Lamb and ‘vanilla wool’ new item.</li>
<li>You can get a white elephant.</li>
</ul>
<h3 id="dreamcatcher">Dreamcatcher</h3>
<p><img src="images/dreamcatcher.png" alt="Dreamcatcher" />
Dreamcatcher amulet for your petz! Protect them!</p>
<ul>
<li>Craftable with: wood, strings and ducky feathers.</li>
<li>To put it: Right click with it on a pet you own.</li>
<li>Now your pet will be protected against other players attacks. But you can still hurt it.</li>
<li>To remove the Dreamcatcher from your pet: Right click on your pet and click on the Dreamcatcher image. Another option is to kill your pet, it will drop the dreamcatcher.</li>
</ul>
<h3 id="whistle">Whistle</h3>
<p><img src="images/whistle.png" alt="Whistle" />
Call your petz anywhere it is.</p>
<ul>
<li>Put names to pets you want to call.</li>
<li>Use a Whistle: A list of pets with name and of your own will appear.</li>
<li>Click on the pet to call it.</li>
</ul>
<h3 id="orders">Orders</h3>
<p>You can give orders to tamed petz.</p>
<ul>
<li>Stand here: It stands fixed at the current pos.</li>
<li>Follow: It will follow you.</li>
<li>Guard: Wild animals (lion &amp; grizzly) will attack any player close them, but not you.</li>
<li>Fly, Alight: For birds.</li>
</ul>
<h3 id="bird-stand">Bird Stand</h3>
<p><img src="images/birdstand_item.png" alt="Birstand Item" />
<img src="images/birdstand.png" alt="Birstand" /></p>
<ul>
<li>Capture your parrot with the Bug Net.</li>
<li>Put it on the bird stand (right-click)</li>
</ul>
<h3 id="barn">Barn</h3>
<p><img src="images/barn.png" alt="Barn" />
Do create livestocks with the aid of fences.</p>
<h3 id="silk-farm">Silk Farm</h3>
<p><img src="images/silk_stuff.png" alt="Silk Stuff" /></p>
<ul>
<li>You can get cocoons. A cocoon is silk indeed.</li>
<li>Also you can capture or breed moths/silkworns to make a Silk Farm.</li>
<li>Create a closed facility. Create a bed of leaves. Put inside some moths and/or silkworms. The moths will lay eggs and silkworms will turn into cocoons (be care: they will eat the leaves too).</li>
</ul>
<h4 id="spinning-wheel">Spinning Wheel</h4>
<p><img src="images/spiniing_wheel.png" alt="Spinning Wheel" /></p>
<ul>
<li>Create a Spinning Wheel to get Silk Bobbins. Its a one node size item, so put on a node-table.</li>
</ul>
<p>Instructions to craft a Spinnig Wheel:</p>
<ul>
<li>A previous bobbin has to be created by hand (3 sticks and 6 silkworm coccons)</li>
<li>You have to note that making bobbins by hand is more expensive (the double) than in the spinning wheel.</li>
<li>The first time your place a Spinning Wheel, that bobbin is already incorporated, only you have to add two more.</li>
</ul>
<p>Instructions to use:</p>
<ul>
<li>You need to put in the Spinning Wheel (right-click) 3 Silkworns Cocoons. Then a Silk Bobbin will be created. Right-click again to get the bobbin.</li>
</ul>
<h4 id="prince-armor">Prince Armor</h4>
<p><img src="images/prince_armor_stuff.png" alt="Prince Armor Stuff" />
<img src="images/prince_armor.png" alt="Prince Armor" /></p>
<ul>
<li>It requires the 3D Armor mod!</li>
<li>You can create a super expensive and exquisite Prince Armor thanks to silk.</li>
</ul>
<h3 id="honey-farm">Honey Farm</h3>
<p><img src="images/honey_stuff.png" alt="Honey Stuff" /></p>
<ul>
<li>The limit of honey by behive is 10 (max_honey_behive setting in petz.conf).</li>
<li>You can collect honey from a behive with an empty bottle (right click).</li>
<li>You can eat the honey. Honey is very powerful in order to recover your health.</li>
<li>Each behive contains three bees (max_bees_behive in petz.conf). A artificially created behive only one.</li>
<li>Bees go out the behive to get pollen, but only if the honey in their behive is below 10. Then they return to their behive to create honey.</li>
<li>If you destroy a behive all their bees will die. Six honeycomb will be dropped.</li>
<li>You can create a behive with 6 honeycombs and one captured worker bee.</li>
<li>Player created behives only will have one bee when placed. But you can add more captured bees to a behive (right click) till the limit. Be care: If you put manually a new bee on a behive and the limit is reached, a bee that would be out when come back will die when entering the behive, in order the limit being respected.</li>
<li>If you put an igniter or a torch below a behive (til 4 nodes), the bees inside will go out.</li>
<li>You can get Beeswax cooking Honeycombs.</li>
<li>You can get Beeswax Candles crafting Beewax with a string.</li>
<li>Trick: Put some flowers surrounding the behive to start the production of honey.</li>
<li>Trick: Point to a behive to known its statistics about the honey and bees (currently inside).</li>
</ul>
<p>Note: Take into account that if there are flowers close the behive a bee will go to them to collect pollen and inmediatelly will return back to the behive. If you want to see bees flying surrounding the behive, the behive should be full of honey so the bees can go for a walk far away. Also bees remain inside the behive at night.</p>
<h4 id="settings">Settings</h4>
<ul>
<li>Max honey by behive.
max_honey_behive = 10 (by default)</li>
<li>Max bees in a behive.
max_bees_behive = 3 (by default)</li>
<li>Outing rate: A “bee_outing_ratio=1â€<C3A2> means that a bee inmediatelly go out the behive for pollen
bee_outing_ratio = 20 (by default)
Note: Take into account that if there are flowers close the behive a bee will go to them to collect pollen and inmediatelly will return back to the behive. If you want to see bees flying surrounding the behive, the behive should be full of honey so the bees can go for a walk far away. Also bees remain inside the behive at night.</li>
<li>Initial honey behive: It indicates the initial honey amount on a created behive.
initial_honey_behive = 3 (by default)</li>
</ul>
<h3 id="bonemeal">Bonemeal</h3>
<ul>
<li>Install the bonemeal mod and convert your petz bones into fertilizer to grown plants faster.</li>
</ul>
:ET

View File

@ -0,0 +1,25 @@
I"3<h2 id="a-minecraft-style-game-do-construct-with-blocks-play-online-fun">A Minecraft style game. Do construct with blocks. Play online. Fun!</h2>
<ul>
<li>An open world to interact to.</li>
<li>Game modes: Creative &amp; Survival.</li>
<li>Make your dreamed constructions.</li>
<li>Farming.</li>
<li>Animals to tame &amp; monsters to kill.</li>
<li>Play online through servers around the whole world.</li>
<li>License: LGPL 2.1+. Share the game with your friends/family and do not care about licenses!</li>
<li>Engine: Minetest</li>
<li>Languages: English/Spanish/Plus other.</li>
<li>Platforms: Windows/Linux/Android</li>
</ul>
<h3 id="download">Download</h3>
<ul class="fa-ul">
<li><i class="fa-li fa fa-download"></i></li>
</ul>
<h3 id="mods">Mods</h3>
<p><a href="petz.html">Petz</a></p>
:ET

7
petz/petz/docs/404.html Normal file
View File

@ -0,0 +1,7 @@
---
layout: default
---
## No such thing as that, sorry
Page Not Found.

21
petz/petz/docs/LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Shu Uesugi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

5
petz/petz/docs/README.md Normal file
View File

@ -0,0 +1,5 @@
This is as Jekyll theme built to make single page websites, articles, or literary masterpieces readable anywhere.
### [Demo and Documentation](https://adueck.github.io/good-clean-read)
Built on top of <a href="http://chibicode.github.io/solo">Solo</a>, by [Shu Uesugi](https://github.com/chibicode)

View File

@ -0,0 +1,13 @@
# Site settings
title: Bogart Game
tag_text: Bogart Game
description: A responsive template for publishing single-page websites, articles that are easy on the eyes
url: "http://127.0.0.1:4000"
baseurl: ""
font-awesome-include: true # make this false if you don't need font-awesome
# Build settings
markdown: kramdown
exclude: ["README.md"]

View File

@ -0,0 +1,49 @@
<div style="margin-bottom: 1em;">
<ul class="rrssb-buttons rrssb-1">
<li class="rrssb-email">
<!-- Replace subject with your message using URL Endocding: http://meyerweb.com/eric/tools/dencoder/ -->
<a href="mailto:">
<span class="rrssb-icon"><svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28"><path d="M20.11 26.147c-2.335 1.05-4.36 1.4-7.124 1.4C6.524 27.548.84 22.916.84 15.284.84 7.343 6.602.45 15.4.45c6.854 0 11.8 4.7 11.8 11.252 0 5.684-3.193 9.265-7.398 9.3-1.83 0-3.153-.934-3.347-2.997h-.077c-1.208 1.986-2.96 2.997-5.023 2.997-2.532 0-4.36-1.868-4.36-5.062 0-4.75 3.503-9.07 9.11-9.07 1.713 0 3.7.4 4.6.972l-1.17 7.203c-.387 2.298-.115 3.3 1 3.4 1.674 0 3.774-2.102 3.774-6.58 0-5.06-3.27-8.994-9.304-8.994C9.05 2.87 3.83 7.545 3.83 14.97c0 6.5 4.2 10.2 10 10.202 1.987 0 4.09-.43 5.647-1.245l.634 2.22zM16.647 10.1c-.31-.078-.7-.155-1.207-.155-2.572 0-4.596 2.53-4.596 5.53 0 1.5.7 2.4 1.9 2.4 1.44 0 2.96-1.83 3.31-4.088l.592-3.72z"/></svg></span>
<span class="rrssb-text">email</span>
</a>
</li>
<li class="rrssb-facebook">
<!-- Replace with your URL. For best results, make sure you page has the proper FB Open Graph tags in header:
https://developers.facebook.com/docs/opengraph/howtos/maximizing-distribution-media-content/ -->
<a href="https://www.facebook.com/sharer/sharer.php?u=" class="popup">
<span class="rrssb-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 29 29"><path d="M26.4 0H2.6C1.714 0 0 1.715 0 2.6v23.8c0 .884 1.715 2.6 2.6 2.6h12.393V17.988h-3.996v-3.98h3.997v-3.062c0-3.746 2.835-5.97 6.177-5.97 1.6 0 2.444.173 2.845.226v3.792H21.18c-1.817 0-2.156.9-2.156 2.168v2.847h5.045l-.66 3.978h-4.386V29H26.4c.884 0 2.6-1.716 2.6-2.6V2.6c0-.885-1.716-2.6-2.6-2.6z"/></svg></span>
<span class="rrssb-text">facebook</span>
</a>
</li>
<li class="rrssb-twitter">
<!-- Replace href with your Meta and URL information -->
<a href="https://twitter.com/intent/tweet?text="
class="popup">
<span class="rrssb-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 28 28">
<path d="M24.253 8.756C24.69 17.08 18.297 24.182 9.97 24.62c-3.122.162-6.22-.646-8.86-2.32 2.702.18 5.375-.648 7.507-2.32-2.072-.248-3.818-1.662-4.49-3.64.802.13 1.62.077 2.4-.154-2.482-.466-4.312-2.586-4.412-5.11.688.276 1.426.408 2.168.387-2.135-1.65-2.73-4.62-1.394-6.965C5.574 7.816 9.54 9.84 13.802 10.07c-.842-2.738.694-5.64 3.434-6.48 2.018-.624 4.212.043 5.546 1.682 1.186-.213 2.318-.662 3.33-1.317-.386 1.256-1.248 2.312-2.4 2.942 1.048-.106 2.07-.394 3.02-.85-.458 1.182-1.343 2.15-2.48 2.71z"
/>
</svg>
</span>
<span class="rrssb-text">twitter</span>
</a>
</li>
<li class="rrssb-linkedin">
<!-- Replace href with your meta and URL information -->
<a href="http://www.linkedin.com/shareArticle?mini=true&amp;url=" class="popup">
<span class="rrssb-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 28"><path d="M25.424 15.887v8.447h-4.896v-7.882c0-1.98-.71-3.33-2.48-3.33-1.354 0-2.158.91-2.514 1.802-.13.315-.162.753-.162 1.194v8.216h-4.9s.067-13.35 0-14.73h4.9v2.087c-.01.017-.023.033-.033.05h.032v-.05c.65-1.002 1.812-2.435 4.414-2.435 3.222 0 5.638 2.106 5.638 6.632zM5.348 2.5c-1.676 0-2.772 1.093-2.772 2.54 0 1.42 1.066 2.538 2.717 2.546h.032c1.71 0 2.77-1.132 2.77-2.546C8.056 3.593 7.02 2.5 5.344 2.5h.005zm-2.48 21.834h4.896V9.604H2.867v14.73z"/></svg></span>
<span class="rrssb-text">linkedin</span>
</a>
</li>
<li class="rrssb-googleplus">
<a href="https://plus.google.com/share?url=" class="popup">
<span class="rrssb-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M21 8.29h-1.95v2.6h-2.6v1.82h2.6v2.6H21v-2.6h2.6v-1.885H21V8.29zM7.614 10.306v2.925h3.9c-.26 1.69-1.755 2.925-3.9 2.925-2.34 0-4.29-2.016-4.29-4.354s1.885-4.353 4.29-4.353c1.104 0 2.014.326 2.794 1.105l2.08-2.08c-1.3-1.17-2.924-1.883-4.874-1.883C3.65 4.586.4 7.835.4 11.8s3.25 7.212 7.214 7.212c4.224 0 6.953-2.988 6.953-7.082 0-.52-.065-1.104-.13-1.624H7.614z"/></svg> </span>
<span class="rrssb-text">google+</span>
</a>
</li>
</ul>
</div>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="{{ site.description }}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ site.title }}</title>
<link rel="stylesheet" href="{{ site.baseurl }}css/normalize.css">
<link rel="stylesheet" href="{{ site.baseurl }}css/solo.css">
<link rel="stylesheet" href="{{ site.baseurl }}css/syntax.css">
{% if site.font-awesome-include %}<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">{% endif %}
<link rel="stylesheet" href="{{ site.baseurl }}css/rrssb.css">
<script src="{{ site.baseurl }}scripts/jquery.js"></script>
<link rel="canonical" href="{{ site.url }}" />
</head>
<body>
<article>
<div class="container">
<h1><a href="./">{{ site.tag_text }}</a></h1>
{{ content }}
</div>
</article>
<script src="{{ site.baseurl }}scripts/rrssb.min.js"></script>
</body>
</html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ site.title }}</title>
<link rel="stylesheet" href="../css/normalize.css">
<link rel="stylesheet" href="../css/solo.css">
</head>
<body>
<article>
<div class="container">
<h3>{{ page.title }}</h3>
{{ content }}
</div>
</article>
</body>
</html>

107
petz/petz/docs/add_petz.md Normal file
View File

@ -0,0 +1,107 @@
An example to add a petz: mouse
1. Edit the 'petz.conf' file
- Open petz.conf and add your petz to the end of the 'petz_list'.
You have to add a comma and 'mouse'.
Warning: Do not put blank spaces.
- In the 'Spawn Mobs?' section:
Add the following line at the end:
mouse_spawn = true
- In the 'Specific Settings for Mobs' section:
Add at the end the following:
##Mouse Specific
#To follow/tame and breed:
mouse_follow = petz:cheese
mouse_spawn_chance = 0.6
mouse_spawn_nodes = default:dirt_with_grass
mouse_predators = petz:kitty
#change here if you want it to spawn only at a one biome
#or leave 'default' for all the biomes:
mouse_spawn_biome = default
- If you want to spawn a herd of mouses, i.e. 4, add:
mouse_spawn_herd = 4
- As you defined kitty as the mouse predator, now you have to define mouse as prey in its settings.
Add (or edit if existed) the following line to "Kitty Specific":
kitty_preys = petz:mouse
2. Create a petz file where the petz will be defined.
But it is better to take an old already created one as template.
The better for mouse is piggy: no tamagochi, no orders.
Open 'piggy_mobkit.lua' and save as 'mouse_mobkit.lua'
3. Edit the 'mouse_mobkit.lua'.
- Firstly you have to replace all the 'piggy' coincidences to 'mouse'
With the aid of you text editor replace:
piggy -> mouse
Piggy -> Mouse
PIGGY -> MOUSE
- Edit the petz charateristics as you like:
- scale_model, mesh, textures, collisionbox, etc.
4. Save the 'mouse_mobkit.lua'
5. ¡DONE!
###Extra
####If you have to create a bird use 'parrot_mobkit.lua' as template.
####If you want to create a domestic pet use 'kitty_mobkit.lua' as template.
####If you want to create a wild animal use 'lion_mobkit.lua' as template.
###Tamagochi mode
If you can your mouse with this mode add/edit:
init_tamagochi_timer = false,
####Bloody Mode
In petz.conf set:
blood = true
You can set a custom texture in the hardcoded petz definition:
blood_texture = ""
You can disable the blood individually in the hardcoded petz definition:
no_blood = true
####Spawn
There is a set of spawn settings you could kie to add to the 'minetest.register_entity' definition:
spawn_at_night = true, --only spawns at night
die_at_daylight = false, --it dies at dawn
min_height = 0, --min height to spawn (0= sea level)
max_height = 30, --max height to spawn (0= sea level)
min_daylight_level = 0, --min light to spawn (min 0)
max_daylight_level = 8, --max light to spawn (max 15)
####Noxious Nodes
If mob in node, then damage it per second.
In example:
noxious_nodes = {
{name = "air", where ="entity", damage = 1},
},
name = name of the node
where = "stand" or "entity" (by default "entity")
damage = damage points (by default 1)
Note: Lava already makes damage so it is not necessary being defined.

406
petz/petz/docs/css/normalize.css vendored Normal file
View File

@ -0,0 +1,406 @@
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block;
}
/**
* Correct `inline-block` display not defined in IE 8/9.
*/
audio,
canvas,
video {
display: inline-block;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address `[hidden]` styling not present in IE 8/9.
* Hide the `template` element in IE, Safari, and Firefox < 22.
*/
[hidden],
template {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/**
* Remove the gray background color from active links in IE 10.
*/
a {
background: transparent;
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari 5, and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/**
* Address styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Correct font family set oddly in Safari 5 and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
/**
* Improve readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre-wrap;
}
/**
* Set consistent quote types.
*/
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* ==========================================================================
Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9.
*/
img {
border: 0;
}
/**
* Correct overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* ==========================================================================
Figures
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari 5.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Correct font family not being inherited in all browsers.
* 2. Correct font size not being inherited in all browsers.
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
*/
button,
input,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 2 */
margin: 0; /* 3 */
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

File diff suppressed because one or more lines are too long

269
petz/petz/docs/css/solo.css Normal file
View File

@ -0,0 +1,269 @@
@import url(https://fonts.googleapis.com/css?family=Open+Sans:300,300italc,400,400italic,500,700);
html {
font: 18px/1.6 'Open Sans', sans-serif;
}
@media (max-width: 325px) {
html { font: 17px/1.6 'Open Sans', sans-serif; }
}
body {
margin: 2rem 0 5rem;
color: #222;
}
@media (min-width: 30rem) {
body {
margin-top: 5rem;
}
}
a {
color: #0074d9; /* From http://clrs.cc */
text-decoration: none;
}
a:hover, a:focus {
text-decoration: underline;
}
h1, h2, h3, h4, h5, h6 {
margin: 0 0 0.5rem -0.1rem /* align left edge */;
color: #111;
text-rendering: optimizeLegibility;
font-family: 'Open Sans', serif;
line-height: 1.2
}
@media (max-width: 750px) {
h1, h2, h3, h4, h5, h6 {
margin-left: 0 !important;
margin-right: 0 !important;
}
}
h1 {
font-size: 2.5rem;
margin-bottom: 7rem;
font-weight: 700;
margin-left: -2rem;
margin-right: -2rem;
}
@media (min-width: 30rem) {
h1 {
font-size: 4rem;
margin-bottom: 10rem;
}
}
h1 a {
color: inherit;
}
h2 {
margin-top: 2rem;
font-size: 1.75rem;
font-weight: 500;
margin-bottom: 5rem;
color: #555;
text-align: right;
margin-right: -4rem;
}
@media (min-width: 30rem) {
h2 {
margin-top: 2.5rem;
font-size: 1.75rem;
margin-bottom: 8rem;
margin-right: -4rem;
}
}
h3 {
margin: 2rem -2rem 1.75rem -2rem;
margin-top: 2rem;
font-size: 1.75rem;
}
@media (min-width: 30rem) {
h3 {
margin-top: 2.5rem;
font-size: 2rem;
margin-bottom: 1.5rem;
}
}
h4, h5, h6 {
margin: 1.5rem -1rem 1.5rem -1rem;
font-size: 1.5rem;
}
p, ul, ol, dl, table, pre, blockquote {
margin-top: 0;
margin-bottom: 1.5rem;
}
ul, ol {
padding-left: 1.5rem;
}
dd {
margin-left: 1.5rem;
}
blockquote {
margin-left: 0.75rem;
margin-right: 0;
padding: 0rem 0.8rem;
border-left: .3rem solid #ccc;
color: #555;
}
blockquote p:last-child {
margin-bottom: 0;
}
.footnote {
color: #444;
}
.center {
display:inline-block;
margin: 0 auto;
}
hr {
border: none;
margin: 1.5rem 0;
border-bottom: 1px solid #ccc;
position: relative;
top: -1px;
}
.img, .container iframe {
max-width: 100%;
}
a {
word-wrap: break-word;
}
.container img {
margin: 2em auto 2em auto;
display: block;
max-width: 75%;
}
@media (max-width: 635px) {
.container img {
max-width: 100%
}
}
table {
width: 100%;
border: 1px solid #ccc;
border-collapse: collapse;
}
td, th {
padding: .25rem .5rem;
border: 1px solid #ccc;
}
pre, code {
font-family: monospace;
background-color: #eee;
}
pre {
padding: .5rem 1rem;
font-size: 0.8rem;
}
code {
padding: .1rem .25rem;
}
pre > code {
padding: 0;
}
.container {
max-width: 625px;
margin: 0 auto;
padding: 0 0.75rem;
}
.sharing {
text-align: center;
}
.date {
text-align: right;
font-size: 75%;
font-style: italic;
}
@media (max-width: 635px) {
.sharing {
font-size: 85%;
}
}
/* This gets Google to fall into place */
.social {
text-align: right;
}
.topsocial {
margin-bottom: 5em;
}
/* This gets Facebook to fall into place */
.social iframe {
vertical-align: middle;
}
/* Set an optional width for your button wrappers */
.social span {
display: inline-block;
width: 110px;
}
/* Adjust the widths individually if you like */
.social .google {
width: 75px;
}
.button {
margin-top: 2em;
margin-left: 1em;
display: inline-block;
border: 2px solid #111;
border-radius: 0.4em;
padding: 0.1em 0.75em;
font-size: 17px;
color: #111;
text-align: center;
}
.button:hover {
color: white;
background-color: #111;
cursor: pointer;
text-decoration: none;
transition: 0.5s;
}
.Facebook {
transform: scale(1.25);
}
.sharing-buttons {
width: 100%;
}
}

View File

@ -0,0 +1,66 @@
.hll { background-color: #ffffcc }
/*{ background: #f0f3f3; }*/
.c { color: #999; } /* Comment */
.err { color: #AA0000; background-color: #FFAAAA } /* Error */
.k { color: #006699; } /* Keyword */
.o { color: #555555 } /* Operator */
.cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
.cp { color: #009999 } /* Comment.Preproc */
.c1 { color: #999; } /* Comment.Single */
.cs { color: #999; } /* Comment.Special */
.gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #FF0000 } /* Generic.Error */
.gh { color: #003300; } /* Generic.Heading */
.gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
.go { color: #AAAAAA } /* Generic.Output */
.gp { color: #000099; } /* Generic.Prompt */
.gs { } /* Generic.Strong */
.gu { color: #003300; } /* Generic.Subheading */
.gt { color: #99CC66 } /* Generic.Traceback */
.kc { color: #006699; } /* Keyword.Constant */
.kd { color: #006699; } /* Keyword.Declaration */
.kn { color: #006699; } /* Keyword.Namespace */
.kp { color: #006699 } /* Keyword.Pseudo */
.kr { color: #006699; } /* Keyword.Reserved */
.kt { color: #007788; } /* Keyword.Type */
.m { color: #FF6600 } /* Literal.Number */
.s { color: #d44950 } /* Literal.String */
.na { color: #4f9fcf } /* Name.Attribute */
.nb { color: #336666 } /* Name.Builtin */
.nc { color: #00AA88; } /* Name.Class */
.no { color: #336600 } /* Name.Constant */
.nd { color: #9999FF } /* Name.Decorator */
.ni { color: #999999; } /* Name.Entity */
.ne { color: #CC0000; } /* Name.Exception */
.nf { color: #CC00FF } /* Name.Function */
.nl { color: #9999FF } /* Name.Label */
.nn { color: #00CCFF; } /* Name.Namespace */
.nt { color: #2f6f9f; } /* Name.Tag */
.nv { color: #003333 } /* Name.Variable */
.ow { color: #000000; } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #FF6600 } /* Literal.Number.Float */
.mh { color: #FF6600 } /* Literal.Number.Hex */
.mi { color: #FF6600 } /* Literal.Number.Integer */
.mo { color: #FF6600 } /* Literal.Number.Oct */
.sb { color: #CC3300 } /* Literal.String.Backtick */
.sc { color: #CC3300 } /* Literal.String.Char */
.sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
.s2 { color: #CC3300 } /* Literal.String.Double */
.se { color: #CC3300; } /* Literal.String.Escape */
.sh { color: #CC3300 } /* Literal.String.Heredoc */
.si { color: #AA0000 } /* Literal.String.Interpol */
.sx { color: #CC3300 } /* Literal.String.Other */
.sr { color: #33AAAA } /* Literal.String.Regex */
.s1 { color: #CC3300 } /* Literal.String.Single */
.ss { color: #FFCC33 } /* Literal.String.Symbol */
.bp { color: #336666 } /* Name.Builtin.Pseudo */
.vc { color: #003333 } /* Name.Variable.Class */
.vg { color: #003333 } /* Name.Variable.Global */
.vi { color: #003333 } /* Name.Variable.Instance */
.il { color: #FF6600 } /* Literal.Number.Integer.Long */
.css .o,
.css .o + .nt,
.css .nt + .nt { color: #999; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Some files were not shown because too many files have changed in this diff Show More