commit f2885566414261ff3fcafbd33f586a76026cbcc2 Author: Sokomine Date: Fri Oct 5 20:06:53 2012 +0200 upload diff --git a/README.md b/README.md new file mode 100644 index 0000000..89f56ee --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +Mod for Minetest that adds a guide which will lead you to specified coordinates + +Not finished yet! Coordinates are hardcoded so far. May not work relieably. + +To invoke the guide, type /guide in the chat. It looks like a MESE-node streched in hight. +If the distance between the guide and you grows too big, the guide will "beam" back to you. diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..de482c8 --- /dev/null +++ b/init.lua @@ -0,0 +1,161 @@ + +-- TODO: stop if player is idle + +minetest.register_entity( "guide_arrow:arrow", { + hp_max = 1, + physical = false, + + collisionbox = {-0.4, -1, -0.4, 0.4, 1, 0.4}, + visual = "cube", --"upright_sprite", + visual_size = {x=1, y=2}, + textures = {"signsplus_wooden_arrow_right.png","default_mese.png","default_mese.png","default_mese.png","default_mese.png","default_mese.png"}, + makes_footstep_sound = true, + + target = nil, + speed = nil, + range = nil, + range_y = nil, + after = nil, + after_param = nil, + + sum_dtime = 0; + + guide_owner = 0; -- player whose guide this is + guide_owner_name = 0; + has_sent_init_message = 0; + + on_step = function(self, dtime) + -- it is enough to look about once per second if there is anything to do + self.sum_dtime = self.sum_dtime + dtime; + + if( self.has_sent_init_message ~= 1 and self.guide_owner_name ~= nil ) then + + self.guide_owner = minetest.env:get_player_by_name(self.guide_owner_name); + self.dtime_sum = 100; -- force guide to check positions + + if( self.guide_owner ~= nil ) then + self.target = self.object:getpos(); -- has been created at the target position + minetest.chat_send_player(self.guide_owner_name, "guide_arrow: Hello "..tostring(self.guide_owner_name)..". I am your guide. Please follow me to coordinates ".. + tostring( math.floor(self.target.x ))..","..tostring( math.floor(self.target.y ))..","..tostring( math.floor(self.target.z )).. + ". If you loose sight of me, just wait until I reappear. You have to take care of the surrounding area on your own. ".. + "If you want to get rid of me, just punch me once."); + self.has_sent_init_message = 1; + end + end + + if( (self.guide_owner == nil or self.target == nil or self.guide_owner == 0)) then + self.object:remove(); + else + if( self.sum_dtime > 1 and self.has_sent_init_message == 1 and self.guide_owner ~= nil and self.target ~= nil ) then + + --minetest.chat_send_player("singleplayer", "guide_arrow: on_step called after "..tostring( self.sum_dtime )); + self.sum_dtime = 0; + + -- get the location of the player + local pos = self.guide_owner:getpos(); + local my_pos = self.object:getpos(); + + local dist_to_owner = ( (pos.x-my_pos.x)^2 + (pos.y-my_pos.y)^2 + (pos.z-my_pos.z)^2)^0.5; + + -- if we got too far from the owner then beam back to him + if( dist_to_owner > 10 ) then + --minetest.chat_send_player(self.guide_owner_name, "guide_arrow: Please follow me."); + --minetest.chat_send_player(name, "guide_arrow: ".." You are at position ".. + -- tostring( pos.x )..","..tostring( pos.y )..","..tostring( pos.z ).."."); + + -- at which direction is the player looking? after all he ought to see the arrow + local dir = self.guide_owner:get_look_dir(); -- getjaw() does not seem to work for players + + --minetest.chat_send_player(name, "guide_arrow: ".." You are looking in direction ".. + -- tostring( dir.x )..","..tostring( dir.y )..","..tostring( dir.z ).."."); + + + -- get a place 3 nodes directly in front of the placer + local arrow_place_dist = 3; + local arrow_place_pos = {x=0, y=0, z=0}; + arrow_place_pos.x = ( pos.x + (dir.x * arrow_place_dist )); + arrow_place_pos.y = ( pos.y+1 ); --+ (dir.y * arrow_place_dist )); + arrow_place_pos.z = ( pos.z + (dir.z * arrow_place_dist )); + + --minetest.chat_send_player(name, "guide_arrow: ".." You are looking at point ".. + -- tostring( arrow_place_pos.x )..","..tostring( arrow_place_pos.y )..","..tostring( arrow_place_pos.z ).."."); + + -- now we have to get a free node the arrow can appear at (inside a node would be impractical); + -- but going too high doesn't help either + local nt; + local offset = 0; + while( (nt == nil or nt.name ~= "air") and (offset<3) ) do + arrow_place_pos.y = arrow_place_pos.y + offset; + nt = minetest.env:get_node( arrow_place_pos ); + offset = offset+1; + end + + self.object:setpos( arrow_place_pos ); + + --minetest.chat_send_player(name, "guide_arrow: ".." First node that is not air (or as high above as we go) ".. + -- tostring( arrow_place_pos.x )..","..tostring( arrow_place_pos.y )..","..tostring( arrow_place_pos.z ).."."); + + -- rotate guide so that it "faces" a direction 90 degree from its target + + local diff = {x=self.target.x-arrow_place_pos.x, y=self.target.y-arrow_place_pos.y, z=self.target.z-arrow_place_pos.z}; + + local yaw = math.atan(diff.z/diff.x); --+math.pi/2; + if diff.z ~= 0 or diff.x > 0 then + yaw = yaw+math.pi; + end + + self.object:setyaw( yaw ); + --minetest.chat_send_player(name, "guide_arrow: ".." Guide rotating to "..tostring( yaw ).." degree."); + + -- set speed + local vec = {x=0, y=0, z=0}; + local amount = (diff.x^2+diff.y^2+diff.z^2)^0.5; + local speed = 3.0; + vec.x = diff.x*speed/amount; + vec.y = diff.y*speed/amount; + vec.z = diff.z*speed/amount; + + self.object:setvelocity( vec ); + --minetest.chat_send_player(name, "guide_arrow: ".." Guide starting to move."); + end + + + -- have we reached the target? + my_pos = self.object:getpos(); + local dist_to_target = ((self.target.x-my_pos.x)^2 + (self.target.y-my_pos.y)^2 + (self.target.z-my_pos.z)^2)^0.5; + if( dist_to_target < 5 ) then + self.object:setvelocity( {x=0, y=0, z=0} ); + minetest.chat_send_player(self.guide_owner_name, "guide_arrow: We have reached the target ".. + tostring( math.floor(self.target.x ))..","..tostring( math.floor(self.target.y ))..","..tostring( math.floor(self.target.z )).. + ", "..tostring( self.guide_owner_name )..". Thank you for having followed me!"); + self.object:remove(); + end + + end + end + end; + +}); + + + + +minetest.register_chatcommand("guide", { + privs = {interact=true}, + params = "[on|off|]", + description = "Show an arrow that guides you to your destination", + func = function(name, param) + + -- actually place the guiding arrow + local target_pos = {x=100, y=15, z=120}; -- TODO: just a suitable testpos +-- local start_pos = minetest.env:get_player_by_name(name):getpos(); + local arrow_entity = minetest.env:add_entity( target_pos, "guide_arrow:arrow"); + minetest.chat_send_player(name, "guide_arrow: ".." Guide placed."); + + -- initialize guide + arrow_entity:get_luaentity().guide_owner_name = name; +-- arrow_entity:get_luaentity().target = target_pos; + + end +}); +