-- string function string:split(inSplitPattern, outResults) if not outResults then outResults = {} end local theStart = 1 local theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) while theSplitStart do table.insert( outResults, string.sub( self, theStart, theSplitStart-1 ) ) theStart = theSplitEnd + 1 theSplitStart, theSplitEnd = string.find( self, inSplitPattern, theStart ) end table.insert( outResults, string.sub( self, theStart ) ) return outResults end -- form story.talk_form = "size[8,7.5;]" story.talk_form = story.talk_form..default.gui_colors story.talk_form = story.talk_form..default.gui_bg story.talk_form = story.talk_form.."image[0,0.0;3,8;story_player.png]" story.talk_form = story.talk_form.."label[2.5,0;%s]" story.talk_form = story.talk_form.."image[6,0.0;3,8;story_character_1.png]" story.get_talk_form = function(text) return string.format(story.talk_form, text) end -- hud story.hud = {} minetest.register_on_joinplayer(function(player) if story.generator.players_storys[player:get_player_name()] and story.generator.players_storys[player:get_player_name()].pos then story.hud[player:get_player_name()] = player:hud_add({ hud_elem_type = "waypoint", name = "story", text = "", number = 0x00FF00, world_pos = story.generator.players_storys[player:get_player_name()].pos }) end story.hud[player:get_player_name()] = player:hud_add({ hud_elem_type = "waypoint", name = "story", text = "", number = 0x00FF00, world_pos = {x=0,y=0,z=0} }) end) -- generator story.generator = {} story.generator.parts = {} story.generator.dialogs = {} story.generator.players_storys = {} function story.generator.gen_next_step(player) print("[INFO] generating story...") if not story.generator.players_storys[player:get_player_name()] then print("[ERROR][story] could not find players story") return end local part = story.generator.get_part(story.generator.players_storys[player:get_player_name()].part) if part then story.generator.players_storys[player:get_player_name()].part = story.generator.run(part, player) return else print("[ERROR][story] could not find part file") return end end function story.generator.new_player(player) -- adds a new entry to the story database story.generator.players_storys[player:get_player_name()] = {} story.generator.players_storys[player:get_player_name()].part = "base" end function story.generator.get_part(name) if not name then return end if name == "" then return end if not story.generator.parts[name] then local file = io.open(minetest.get_modpath("story").."/parts/"..name..".part", "r") story.generator.parts[name] = file:read("*all") io.close(file) return story.generator.parts[name] else return story.generator.parts[name] end end function story.generator.get_dialog(name) if not story.generator.dialogs[name] then local file = io.open(minetest.get_modpath("story").."/parts/"..name..".dialog", "r") story.generator.dialogs[name] = file:read("*all") io.close(file) return story.generator.dialogs[name] else return story.generator.dialogs[name] end end function story.generator.run(part, player) local next_part = "" print("[INFO] run script... " .. part) local lines = part:split("\n") if not lines then return "" end for k,v in pairs(lines) do local cmd = v:split(" ") if cmd[1] then print("[INFO] run line... " .. v) if cmd[1] == "$dialog" and cmd[2] then if story.generator.get_dialog(cmd[2]) then story.generator.players_storys[player:get_player_name()].text = story.generator.get_dialog(cmd[2]) end end if cmd[1] == "$create" then story.generator.show(player, {x=0, y=10, z=0}) end -- test cmd if cmd[1] == "$pos" then story.generator.players_storys[player:get_player_name()].pos = {x=0, y=10, z=0} end end end return next_part end function story.generator.show(player, p) -- update waypoint player:hud_remove(story.hud[player:get_player_name()]) story.hud[player:get_player_name()] = player:hud_add({ hud_elem_type = "waypoint", name = "story", text = "", number = 0x00FF00, world_pos = p }) minetest.add_entity(p, "story:human") end minetest.register_on_newplayer(function(player) story.generator.new_player(player) story.generator.gen_next_step(player) end) -- human minetest.register_entity("story:human", { hp_max = 50, physical = true, collisionbox = {-0.4,-1,-0.4, 0.4,1,0.4}, visual = "mesh", visual_size = {x=1, y=1}, textures = {"character.png",}, mesh = "character.x", spritediv = {x=1, y=1}, initial_sprite_basepos = {x=0, y=0}, is_visible = true, makes_footstep_sound = false, automatic_rotate = true, speed = 0, plname = nil, text = nil, on_rightclick = function(self, clicker) if not clicker or not clicker:is_player() then return end if not story.generator.players_storys[clicker:get_player_name()] then return end -- shows the dialog if story.generator.players_storys[clicker:get_player_name()].pos then if vector.distance(self.object:getpos(), story.generator.players_storys[clicker:get_player_name()].pos) < 3 then minetest.show_formspec(clicker:get_player_name(), "story:story", story.get_talk_form(story.generator.players_storys[clicker:get_player_name()].text)) story.generator.gen_next_step(clicker) -- TODO : delete npc after talking with it (or move it some where else) end end end, on_step = function(self, dtime) -- nothing end, }) minetest.register_craftitem("story:human", { description = "Human", inventory_image = "story_character_spawn.png", on_place = function(itemstack, placer, pointed_thing) if pointed_thing.type ~= "node" then return end local p = pointed_thing.above p.y = p.y + 0.5 minetest.add_entity(p, "story:human") if not minetest.setting_getbool("creative_mode") then itemstack:take_item() end return itemstack end, })