mobs_npcs/mobs_api.lua

284 lines
8.0 KiB
Lua
Executable File

--
-- This file adds function to complete the mobs_redo api
--
-- Translator
local S = mobs.translator
local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local vlog = mobs.vlog or "action" --"info"
local vlog = "action" --"info"
local cooldown_mult = 9
if not mobs.npcs then mobs.npcs = {} end
if not mobs.npcs.messages then mobs.npcs.messages = {} end
if not mobs.npcs.messages.random then mobs.npcs.messages.random = {} end
---------------------------------------------------------------------------------------------
-- turn towards the player and stand
-- (based on function from mobf_trader)
---------------------------------------------------------------------------------------------
function get_face_direction(v1, v2)
if v1 and v2 then
if v1.x and v2.x and v1.z and v2.z then
local dx = v1.x - v2.x
local dz = v2.z - v1.z
return math.atan2(dx, dz)
end
end
end
mobs.npcs.turn_to_player = function( self, player )
-- Stand sill and pretend to listen
self.timer = 0
self.object:setvelocity({x = 0, y = 0, z = 0})
self.state = "stand"
mobs:set_animation(self, "stand")
-- Turn to player
if( self.object and self.object.setyaw ) then
self.object:setyaw( get_face_direction( self.object:getpos(), player:getpos() ));
end
end
string.lines_to_table = function(s)
if not s then s = '' end
local t = {}
local n = 1
for line in s:gmatch("[^\r\n]+") do
t[n] = line
n = n + 1
end
return t
end
mobs.npcs.get_textures_array = function(prefix,modfrom)
local n = 0
local tn, tf, fp
local tx = {}
while true do
tn = prefix .. n .. ".png"
tf = minetest.get_modpath(modname) .. "/textures/".. tn
fp = io.open(tf)
if not fp then break end
fp:close()
tx[#tx+1]={tn}
n = n + 1
end
if #tx > 0 then return tx end
end
mobs.npcs.get_mobname = function(self,generic)
local mobname = generic or 'npc'
if self and self._mobname and self._mobname ~= '' then
return self._mobname
end
return mobname
end
mobs.npcs.send_chat_message = function(playername,msg,mobname)
if not mobname then mobname = 'npc' end
if not msg then msg = "" end
return minetest.chat_send_player(playername,'<'..mobname..'> '..msg)
end
mobs.npcs.random_message_on_rightclick = function(self,player,data)
-- Get mob name
local mobname = mobs.npcs.get_mobname(self)
-- Get player name
local playername = player:get_player_name()
-- Say smething
local msg = mobs.npcs.messages.get_random()
mobs.npcs.send_chat_message(playername,msg,mobname)
end
mobs.npcs.message_on_rightclick = function(self,player,data,varname)
-- Get things to say
local str = ""
if not data then data = {} end
if not varname then varname = 'message' end
if data.action then
-- print(dump(data))
-- print(dump(varname))
-- print(data.action[varname])
str = data.action[varname] or "bof"
end
-- Get mobname
local mobname = mobs.npcs.get_mobname(self)
-- Get player name
local playername = player:get_player_name()
-- Say something
local msg = mobs.npcs.messages.get_random_from_string(str)
mobs.npcs.send_chat_message(playername,msg,mobname)
end
local function heal_loop(player,hp_max,c)
local hp = player:get_hp()
local hp = hp + 1
if hp > hp_max then hp = hp_max end
-- Set new hp
player:set_hp(hp)
-- Start couning in case to avoid endless loop in case the player is hurting while healing...
if not c then
c = 1
else
c = c+1
end
-- Start again if health is not maxed
-- And loop as not reached its limit (30)
if ( c <= 30 ) and ( hp < hp_max ) then
minetest.after(1,heal_loop,player,hp_max,c)
end
-- Return diff between hp and hp_max
return hp_max - hp
end
mobs.npcs.heal_on_rightclick = function(self,player,data)
if self._cooldown and self._cooldown > 0 then
mobs.npcs.message_on_rightclick(self,player,data,'message_cooldown')
return
end
-- Get current HP and HP_MAX
-- local hp = player:get_hp()
local hp_max = player:get_properties().hp_max
-- Send message and start healing
mobs.npcs.message_on_rightclick(self,player,data,'message_heal')
dmg = heal_loop(player,hp_max)
-- TODO: Add some effects
self._cooldown = cooldown_mult * dmg
-- Then rest for some time, depending on how much damage were healed
minetest.log(vlog, '['..modname..'] '..'Player '.. player:get_player_name() .. ' was healed by NPC mob at '.. minetest.pos_to_string(player:get_pos()).. '. Cooldown was set to '..self._cooldown..'.' )
end
-- Register messages
-- Input must be either a string or a table of indexed values
-- Non-indexed values in tables will be ignored
mobs.npcs.messages.register_random = function(var)
local t
if type(var) == "table" then
t = var
elseif type(var) == "string" then
t = string.lines_to_table(var)
else
return false
end
local glob = mobs.npcs.messages.random
for _,v in ipairs(t) do
glob[#glob+1]= v
end
mobs.npcs.messages.random = glob
return true
end
-- Define langage (code from intllib mod)
local LANG = minetest.settings:get("language")
if not (LANG and (LANG ~= "")) then LANG = os.getenv("LANG") end
if not (LANG and (LANG ~= "")) then LANG = "en" end
LANG = LANG:sub(1, 2)
-- Reused from mod random_messages
mobs.npcs.messages.get_list_from_file = function(basename)
if not basename then return end
local line_number = 1
local messages = {}
-- Look into the world folder first
local input = io.open(minetest.get_worldpath()..'/'..basename..'.txt',"r")
-- If it fails, try looking elswhere
if not input then
-- Localized default file in the mod folder
local default_input = io.open(minetest.get_modpath(modname)..'/'..basename..'.'..LANG..'.txt',"r")
local output = io.open(minetest.get_worldpath()..'/'..basename..'.txt',"w")
if not default_input then
-- localised file not found, look for a generic default file in the mod folder
default_input = io.open(minetest.get_modpath(modname)..'/'..basename..'.txt',"r")
end
if not default_input then
-- Now we're out of options, blame the admin
-- output:write("Blame the server admin! He/She has probably not edited the random messages yet.\n")
-- output:write("Tell your dumb admin that this line is in (worldpath)/random_messages \n")
-- As fun a the above would be, using default files or leaving this the output empty is now more convenient
minetest.log(vlog, '['..modname..'] '..'No input message file found for "'..basename.. '"... ignoring. Place a file named '.. basename .. '.txt' .. ' in world directory to add messages to the random messages list.' )
else
-- or write default_input content in worldpath message file
minetest.log(vlog, '['..modname..'] '..'No input message file found for "'..basename.. '"... updating world folder data' )
local content = default_input:read("*all")
output:write(content)
end
io.close(output)
if default_input then io.close(default_input) end
input = io.open(minetest.get_worldpath()..'/'..basename..'.txt',"r")
end
-- we should have input by now, so lets read it
for line in input:lines() do
messages[line_number] = line
line_number = line_number + 1
end
-- close it
io.close(input)
return messages
end
-- Fill messages array when server start.
--
local default_messages_file_name = "mobs_npc_messages"
local messages_default = mobs.npcs.messages.get_list_from_file("mobs_npc_messages")
local messages_extra = mobs.npcs.messages.get_list_from_file("mobs_npc_messages_extra")
mobs.npcs.messages.register_random(messages_default)
mobs.npcs.messages.register_random(messages_extra)
function table.count( t )
local i = 0
for k in pairs( t ) do i = i + 1 end
return i
end
function table.random( t )
local rk = math.random( 1, table.count( t ) )
local i = 1
for k, v in pairs( t ) do
if ( i == rk ) then return v, k end
i = i + 1
end
end
mobs.npcs.messages.get_random = function()
return table.random(mobs.npcs.messages.random)
end
mobs.npcs.messages.get_random_from_string = function(str)
local arr = string.lines_to_table(str)
return table.random(arr)
end