-- -- 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