diff --git a/.luacheckrc b/.luacheckrc index 612255a..4f22195 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -3,7 +3,7 @@ read_globals = { "minetest", "core", "nodecore", "dump", "dump2", "vector", - "VoxelManip", "VoxelArea", + "VoxelManip", "VoxelArea", "Raycast", "PseudoRandom", "PcgRandom", "ItemStack", "Settings", diff --git a/README.md b/README.md index 560c85d..8e2650d 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,15 @@ Adds a steel hammer and the powerful version that you can create from it. ## Usage Rightclick to spawn a fling entity in your pointed direction + Punch the fling entity to fling yourself in that direction You will take fall damage if your hammer can spawn a fling entity again (It can do so 5 seconds after punching a fling entity, your wielditem will indicate when the time is up because it will stop moving upwards) To prevent yourself from taking fall damage you need to rightclick the ground you are falling on before you land on it. This can be achieved by holding down rightmouse and aiming at the ground. If you do land with the rightmouse method all entities including players within a 3 node radius will be blasted away from you, the greater the falling velocity the farther they will fly. So flinging yourself downwards in midair results in a bigger blast. +Rightclick the fling entity to throw your hammer, the hammer will return to you after a while, but if it hits a player it will grab that player and allow you to move them around. +Hold down RMB and once the hammer detects that it will throw the player in your look direction and return to you + ## Minetest Game Crafting See code (hammer_of_power/compat/mtg.lua) diff --git a/compat/mtg.lua b/compat/mtg.lua index b3e6f7b..117ce9a 100644 --- a/compat/mtg.lua +++ b/compat/mtg.lua @@ -1,3 +1,33 @@ +-- Register player copy + +minetest.register_entity("hammer_of_power:playercopy", { + initial_properties = { + physical = false, + collide_with_objects = false, + pointable = false, + selectionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3}, + visual = "mesh", + mesh = "character.b3d", + textures = {"character.png"}, + is_visible = true, + static_save = false, + }, + on_step = function(self, dtime) + if self.mimic and self.follow then + local mimic = minetest.get_player_by_name(self.mimic) + + if not mimic or not self.follow:get_luaentity() then self.object:remove() return end + + local pos1 = self.object:get_pos() + local pos2 = self.follow:get_pos() + + self.object:set_yaw(mimic:get_look_horizontal()) + self.object:set_velocity(vector.multiply(vector.direction(pos1, pos2), vector.distance(pos1, pos2)+10)) + end + end +}) + -- Register crafts minetest.register_craft({ diff --git a/init.lua b/init.lua index 4ab8cf9..74ac6bf 100644 --- a/init.lua +++ b/init.lua @@ -221,6 +221,33 @@ minetest.register_entity("hammer_of_power:flingent", { self.object:remove() end end, + on_rightclick = function(self, clicker) + if not clicker:is_player() or not clicker:get_wielded_item():get_name() == "hammer_of_power:hammer" then return end + + local name = clicker:get_player_name() + + if not self.player or name == self.player then + local pos = clicker:get_pos() + local dir = clicker:get_look_dir() + pos.y = pos.y + 1.5 + + clicker:set_wielded_item("") + + local obj = minetest.add_entity( + vector.add(pos, vector.multiply(dir, 1)), + "hammer_of_power:hammerent" + ) + + obj:set_rotation(vector.new(0, 0, math.pi/2+clicker:get_look_vertical())) + obj:set_velocity(vector.multiply(dir, 20)) + + if obj then + obj:get_luaentity().player = name + end + end + + self.object:remove() + end, on_step = function(self, dtime) if not self.timer then self.timer = 0 end @@ -230,6 +257,133 @@ minetest.register_entity("hammer_of_power:flingent", { end, }) +minetest.register_entity("hammer_of_power:hammerent", { + initial_properties = { + physical = true, + collide_with_objects = true, + pointable = true, + selectionbox = {-0.4, -0.4, -0.4, 0.4, 0.4, 0.4}, + collisionbox = {-0.4, -0.4, -0.4, 0.4, 0.4, 0.4}, + visual_size = vector.new(0.4, 0.4, 0.4), + visual = "wielditem", + wield_item = "hammer_of_power:hammer", + is_visible = true, + automatic_face_movement_dir = true, + glow = 4, + static_save = true, + }, + on_step = function(self, dtime) + if not self.timer then self.timer = 0 end + + local vel = self.object:get_velocity() + + if not self.last_vel then + self.last_vel = vel + end + + -- Check for a collision on the x/y/z axis + + if not self.attachment and not vector.equals(self.last_vel, vel) and vector.distance(self.last_vel, vel) > 4 then + local dir = vector.normalize(self.last_vel) + local pos = self.object:get_pos() + + self.object:set_velocity(vector.new()) + self.last_vel = self.object:get_velocity() + + local ray = Raycast(pos, vector.add(pos, vector.multiply(dir, 2)), true, false) + + for pointed in ray do + if pointed ~= nil then + if pointed.type == "object" and pointed.ref:is_player() and pointed.ref:get_player_name() ~= self.player then + self.attached_player = pointed.ref:get_player_name() + self.attachment = true + pointed.ref:set_attach(self.object, "", vector.new(), vector.new()) + local obj = minetest.add_entity(pos, "hammer_of_power:playercopy") + + obj:get_luaentity().follow = self.object + self.mimicobj = obj + obj:get_luaentity().mimic = self.attached_player + end + end + end + end + + self.last_vel = vel + + if self.attachment then + local owner = minetest.get_player_by_name(self.player) + local attached = minetest.get_player_by_name(self.attached_player or "") + + if not owner then + if attached then + attached:set_detach() + end + + self.attachment = nil + self.timer = 2.1 + + return + end + + if owner:get_player_control().RMB and attached then + attached:set_detach() + attached:add_player_velocity(vector.multiply(owner:get_look_dir(), 20)) + self.attachment = nil + self.timer = 2.1 + else + local pos1 = self.object:get_pos() + local pos2 = owner:get_pos() + pos2.y = pos2.y + 1.5 + + pos2 = vector.add(pos2, vector.multiply(owner:get_look_dir(), 6)) + + self.object:set_velocity(vector.multiply(vector.direction(pos1, pos2), vector.distance(pos1, pos2) + 5)) + self.last_vel = self.object:get_velocity() + end + end + + + if not self.attachment and self.timer > 2 then + if not self.player then self.object:remove() return end + + local owner = minetest.get_player_by_name(self.player) + local pos1 = self.object:get_pos() + local pos2 = owner:get_pos() + + pos2.y = pos2.y + 1 + + if owner and vector.distance(pos1, pos2) >= 2 then + self.object:set_velocity(vector.multiply(vector.direction(pos1, pos2), vector.distance(pos1, pos2) + 10)) + self.last_vel = self.object:get_velocity() + else + if owner and owner:get_inventory():add_item("main", "hammer_of_power:hammer"):get_count() > 0 then + minetest.add_item(self.object:get_pos(), "hammer_of_power:hammer") + end + + self.object:remove() + end + elseif not self.attachment then + self.timer = self.timer + dtime + end + end, + on_detach_child = function(self) + self.attachment = false + + if self.mimicobj:get_luaentity() then + self.mimicobj:remove() + end + end, + on_punch = function(self, puncher) + if not self.player or self.player == puncher:get_player_name() then + if puncher:get_inventory():add_item("main", "hammer_of_power:hammer"):get_count() > 0 then + minetest.add_item(self.object:get_pos(), "hammer_of_power:hammer") + end + + self.object:remove() + end + end, +}) + if minetest.get_modpath("default") then minetest.log("action", "[HAMMER_OF_POWER] Loading compat for mtg") dofile(minetest.get_modpath("hammer_of_power").."/compat/mtg.lua") diff --git a/mod.conf b/mod.conf index 3046495..34f6e71 100644 --- a/mod.conf +++ b/mod.conf @@ -1,2 +1,2 @@ name = hammer_of_power -optional_depends = nc_api_all, nc_lux, default +optional_depends = nc_api_all, nc_lux, default, player_api