.
4
petz/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
## Generic ignorable patterns and files
|
||||||
|
*.obj
|
||||||
|
*.blend1
|
||||||
|
user.conf
|
31
petz/.luacheckrc
Normal 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
@ -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
@ -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
@ -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'},
|
||||||
|
}
|
||||||
|
})
|
2
petz/bale/locale/bale.br.tr
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# textdomain: bale
|
||||||
|
Bale=Fardo de feno
|
2
petz/bale/locale/bale.de.tr
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# textdomain: bale
|
||||||
|
Bale=Heuballen
|
2
petz/bale/locale/bale.es.tr
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# textdomain: bale
|
||||||
|
Bale=Paca de heno
|
2
petz/bale/locale/bale.fr.tr
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# textdomain: bale
|
||||||
|
Bale=Botte de foin
|
2
petz/bale/locale/bale.ru.tr
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# textdomain: bale
|
||||||
|
Bale=тюк сена
|
3
petz/bale/mod.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
name = bale
|
||||||
|
description = A bale of hay (wheat)
|
||||||
|
depends = farming
|
BIN
petz/bale/textures/bale_bale.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
5
petz/modpack.conf
Normal 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
113
petz/mokapi/README.md
Normal 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.
|
13
petz/mokapi/api/api_clear_mobs.lua
Normal 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
|
17
petz/mokapi/api/api_commands.lua
Normal 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,
|
||||||
|
})
|
4
petz/mokapi/api/api_consts.lua
Normal 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
|
15
petz/mokapi/api/api_cron.lua
Normal 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
|
84
petz/mokapi/api/api_drops.lua
Normal 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
|
76
petz/mokapi/api/api_feed_tame.lua
Normal 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
|
40
petz/mokapi/api/api_helper_functions.lua
Normal 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
|
43
petz/mokapi/api/api_math.lua
Normal 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
|
||||||
|
|
31
petz/mokapi/api/api_replace.lua
Normal 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
|
33
petz/mokapi/api/api_sound.lua
Normal 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
@ -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
@ -0,0 +1,3 @@
|
|||||||
|
name = mokapi
|
||||||
|
description = A high level API for mobkit
|
||||||
|
depends = mobkit
|
2
petz/petz/CHANGELOG.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
|
9
petz/petz/README.md
Normal 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
@ -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"))()
|
||||||
|
|
40
petz/petz/api/api_back_home.lua
Normal 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
|
62
petz/petz/api/api_bees.lua
Normal 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
|
29
petz/petz/api/api_blood.lua
Normal 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
|
16
petz/petz/api/api_bottled.lua
Normal 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
@ -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
|
25
petz/petz/api/api_brush.lua
Normal 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
|
138
petz/petz/api/api_capture.lua
Normal 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
|
12
petz/petz/api/api_collisionbox.lua
Normal 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
|
21
petz/petz/api/api_colorize.lua
Normal 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
|
3
petz/petz/api/api_colors.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
petz.colors = {}
|
||||||
|
petz.colors["green"] = "#3ADF00"
|
||||||
|
petz.colors["red"] = "#DF013A"
|
24
petz/petz/api/api_convert.lua
Normal 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
|
29
petz/petz/api/api_dam_beaver.lua
Normal 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
|
4
petz/petz/api/api_datetime.lua
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
petz.get_os_month = function()
|
||||||
|
local nowTable= os.date('*t')
|
||||||
|
return nowTable.month
|
||||||
|
end
|
121
petz/petz/api/api_dreamcatcher.lua
Normal 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
|
50
petz/petz/api/api_eggs.lua
Normal 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
|
37
petz/petz/api/api_env_damage.lua
Normal 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
|
103
petz/petz/api/api_feed_tame.lua
Normal 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
@ -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)
|
93
petz/petz/api/api_helper_functions.lua
Normal 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
|
56
petz/petz/api/api_horseshoes.lua
Normal 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
|
||||||
|
|
350
petz/petz/api/api_init_prop.lua
Normal 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
|
33
petz/petz/api/api_lifetime.lua
Normal 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
|
90
petz/petz/api/api_mount.lua
Normal 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
|
24
petz/petz/api/api_nametag.lua
Normal 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
|
3
petz/petz/api/api_on_deactivate.lua
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
function petz.on_deactivate(self)
|
||||||
|
petz.dreamcatcher_save_metadata(self)
|
||||||
|
end
|
112
petz/petz/api/api_on_die.lua
Normal 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
|
123
petz/petz/api/api_on_punch.lua
Normal 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
|
124
petz/petz/api/api_on_rightclick.lua
Normal 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
|
48
petz/petz/api/api_on_step.lua
Normal 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
|
70
petz/petz/api/api_orders.lua
Normal 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
|
108
petz/petz/api/api_particles.lua
Normal 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
|
16
petz/petz/api/api_poop.lua
Normal 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
|
36
petz/petz/api/api_sell_buy.lua
Normal 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
@ -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
@ -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
@ -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
|
161
petz/petz/api/api_squareball.lua
Normal 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,
|
||||||
|
})
|
130
petz/petz/api/api_tamagochi.lua
Normal 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
@ -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
|
24
petz/petz/api/api_wagon.lua
Normal 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
|
95
petz/petz/api/api_whistle.lua
Normal 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)
|
101
petz/petz/api/api_wool_milk.lua
Normal 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
@ -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
@ -0,0 +1 @@
|
|||||||
|
_site
|
@ -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
|
@ -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 & 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 & 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 & 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 -> 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 & 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
|
@ -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 & Survival.</li>
|
||||||
|
<li>Make your dreamed constructions.</li>
|
||||||
|
<li>Farming.</li>
|
||||||
|
<li>Animals to tame & 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
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
## No such thing as that, sorry
|
||||||
|
|
||||||
|
Page Not Found.
|
21
petz/petz/docs/LICENSE
Normal 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
@ -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)
|
13
petz/petz/docs/_config.yml
Normal 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"]
|
49
petz/petz/docs/_includes/sharing.html
Normal 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&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>
|
27
petz/petz/docs/_layouts/default.html
Normal 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>
|
22
petz/petz/docs/_layouts/page.html
Normal 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
@ -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
@ -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;
|
||||||
|
}
|
1
petz/petz/docs/css/rrssb.css
Normal file
269
petz/petz/docs/css/solo.css
Normal 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%;
|
||||||
|
}
|
||||||
|
}
|
66
petz/petz/docs/css/syntax.css
Normal 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; }
|
BIN
petz/petz/docs/images/baby_pony.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
petz/petz/docs/images/beaver.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
petz/petz/docs/images/beaver_dam.png
Normal file
After Width: | Height: | Size: 99 KiB |
BIN
petz/petz/docs/images/beaver_oil.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
petz/petz/docs/images/brush.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
petz/petz/docs/images/calf.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
petz/petz/docs/images/chicken.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
petz/petz/docs/images/chimp.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
petz/petz/docs/images/clownfish.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
petz/petz/docs/images/duck_chicken_farm.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
petz/petz/docs/images/ducky.png
Normal file
After Width: | Height: | Size: 55 KiB |