From cc0798b617b1cef38a541f5e49fb01f5f147f253 Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Sun, 2 Jul 2023 17:17:14 +0100 Subject: [PATCH 1/7] add check to see what hit mob, player or entity for immune_to --- api.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/api.lua b/api.lua index 11ee89d..16a64eb 100644 --- a/api.lua +++ b/api.lua @@ -25,7 +25,7 @@ local use_cmi = minetest.global_exists("cmi") mobs = { mod = "redo", - version = "20230613", + version = "20230702", intllib = S, invis = minetest.global_exists("invisibility") and invisibility or {} } @@ -2873,10 +2873,17 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage) end end + -- check if hit by player item or entity + local hit_item = weapon_def.name + + if not hitter:is_player() then + hit_item = hitter:get_luaentity().name + end + -- check for tool immunity or special damage for n = 1, #self.immune_to do - if self.immune_to[n][1] == weapon_def.name then + if self.immune_to[n][1] == hit_item then damage = self.immune_to[n][2] or 0 From dcc702848f5647363bb2fd4234f5453c5a57793a Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Sat, 15 Jul 2023 08:58:18 +0100 Subject: [PATCH 2/7] can now add nodes to 'runaway_from' table --- api.lua | 17 ++++++++++++++++- api.txt | 4 ++-- readme.MD | 1 + 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/api.lua b/api.lua index 16a64eb..29a4115 100644 --- a/api.lua +++ b/api.lua @@ -25,7 +25,7 @@ local use_cmi = minetest.global_exists("cmi") mobs = { mod = "redo", - version = "20230702", + version = "20230715", intllib = S, invis = minetest.global_exists("invisibility") and invisibility or {} } @@ -2051,6 +2051,7 @@ function mob_class:do_runaway_from() local min_dist = self.view_range + 1 local objs = minetest.get_objects_inside_radius(s, self.view_range) + -- loop through entities surrounding mob for n = 1, #objs do if objs[n]:is_player() then @@ -2102,6 +2103,20 @@ function mob_class:do_runaway_from() self.state = "runaway" self.runaway_timer = 3 self.following = nil + + return + end + + -- check for nodes to runaway from + objs = minetest.find_node_near(s, self.view_range, self.runaway_from, true) + + if objs then + + yaw_to_pos(self, objs, 3) + + self.state = "runaway" + self.runaway_timer = 3 + self.following = nil end end diff --git a/api.txt b/api.txt index cc6514a..cf04172 100644 --- a/api.txt +++ b/api.txt @@ -154,8 +154,8 @@ functions needed for the mob to work properly which contains the following: 'friendly_fire` when set to false, mobs will not be able to harm other mobs of the same type with friendly fire arrows. Defaults to true. - 'runaway_from' contains a table with mob names to run away from, add - "player" to list to runaway from player also. + 'runaway_from' contains a table with mob names or nodesto run away + from, add "player" to list to runaway from player also. 'ignore_invisibility' When true mob will still be able to see and attack player even if invisible (invisibility mod only). 'blood_amount' contains the number of blood droplets to appear when diff --git a/readme.MD b/readme.MD index aba1f0b..ef69acb 100644 --- a/readme.MD +++ b/readme.MD @@ -33,6 +33,7 @@ https://forum.minetest.net/viewtopic.php?f=11&t=9917 * Refactored do_jump and added get_nodes function * Many bug fixes and tweaks to improve performance * Added 'mobs_attack_creatura' setting so that monsters can attack Creatura mobs +* Nodes can be added to 'runaway_from' table ### Version 1.56 From 3106c4c859594348375cdbbd2d110af9051e55f4 Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Thu, 20 Jul 2023 12:25:27 +0100 Subject: [PATCH 3/7] change mobs_swing.ogg to mono --- sounds/mobs_swing.ogg | Bin 6895 -> 6194 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/sounds/mobs_swing.ogg b/sounds/mobs_swing.ogg index ffe6a9ce1407fcb1a9bc34a194be7a230183ad35..30609f0102776fea0e9911c6c899b8136bfe77f6 100644 GIT binary patch literal 6194 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 literal 6895 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 q_rlfhT4(FDGv+6T(tLS3{&=iPU+J3hm^ Date: Wed, 26 Jul 2023 13:43:06 +0100 Subject: [PATCH 4/7] better MineClone2 compatibility for api, items and crafts --- api.lua | 40 ++++++------------ compatibility.lua | 10 +++++ crafts.lua | 103 ++++++++++++++++++++++++++-------------------- init.lua | 6 +++ mount.lua | 14 ++++++- readme.MD | 1 + 6 files changed, 100 insertions(+), 74 deletions(-) create mode 100644 compatibility.lua diff --git a/api.lua b/api.lua index 29a4115..9be3d1d 100644 --- a/api.lua +++ b/api.lua @@ -23,12 +23,11 @@ end -- CMI support check local use_cmi = minetest.global_exists("cmi") -mobs = { - mod = "redo", - version = "20230715", - intllib = S, - invis = minetest.global_exists("invisibility") and invisibility or {} -} +mobs.mod = "redo" +mobs.version = "20230726" +mobs.intllib = S +mobs.invis = minetest.global_exists("invisibility") and invisibility or {} + -- localize common functions local pi = math.pi @@ -132,12 +131,6 @@ local aoc_range = tonumber(settings:get("active_block_range")) * 16 local creatura = minetest.get_modpath("creatura") and settings:get_bool("mobs_attack_creatura") == true --- default nodes -local node_ice = "default:ice" -local node_snowblock = "default:snowblock" -local node_snow = "default:snow" - -mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "default:dirt" mobs.mob_class = { stepheight = 1.1, @@ -1252,7 +1245,7 @@ function mob_class:do_jump() and (self.walk_chance == 0 or minetest.registered_items[self.looking_at].walkable) and not blocked and not self.facing_fence - and self.looking_at ~= node_snow then + and self.looking_at ~= mobs.node_snow then local v = self.object:get_velocity() @@ -2271,22 +2264,13 @@ function mob_class:do_states(dtime) if is_node_dangerous(self, self.standing_in) then local s = self.object:get_pos() - local lp + local grps = {} - -- is there something I need to avoid? - if self.water_damage > 0 - and self.lava_damage > 0 then + if self.water_damage > 0 then table.insert(grps, "group:water") end + if self.fire_damage > 0 then table.insert(grps, "group:fire") end + if self.lava_damage > 0 then table.insert(grps, "group:lava") end - lp = minetest.find_node_near(s, 1, {"group:water", "group:igniter"}) - - elseif self.water_damage > 0 then - - lp = minetest.find_node_near(s, 1, {"group:water"}) - - elseif self.lava_damage > 0 then - - lp = minetest.find_node_near(s, 1, {"group:igniter"}) - end + local lp = minetest.find_node_near(s, 1, grps) if lp then @@ -2295,7 +2279,7 @@ function mob_class:do_states(dtime) lp = minetest.find_nodes_in_area_under_air( {x = s.x - 5, y = s.y , z = s.z - 5}, {x = s.x + 5, y = s.y + 2, z = s.z + 5}, - {"group:soil", "group:stone", "group:sand", node_ice, node_snowblock}) + {"group:cracky", "group:crumbly", "group:choppy", "group:solid"}) -- did we find land? if lp and #lp > 0 then diff --git a/compatibility.lua b/compatibility.lua new file mode 100644 index 0000000..d863098 --- /dev/null +++ b/compatibility.lua @@ -0,0 +1,10 @@ + +local mc2 = minetest.get_modpath("mcl_core") + +mobs.node_ice = minetest.registered_aliases["mapgen_ice"] or "mcl_core:ice" +mobs.node_snow = minetest.registered_aliases["mapgen_snow"] or "mcl_core:snow" +mobs.node_snowblock = minetest.registered_aliases["mapgen_snowblock"] or "mcl_core:snowblock" +mobs.node_stone = minetest.registered_aliases["mapgen_stone"] or "mcl_core:stone" +mobs.node_dirt = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" + +mobs.fallback_node = mobs.node_dirt diff --git a/crafts.lua b/crafts.lua index aa8edca..ca92c2a 100644 --- a/crafts.lua +++ b/crafts.lua @@ -1,5 +1,24 @@ local S = mobs.intllib +local mc2 = minetest.get_modpath("mcl_core") + +-- recipe items +local items = { + paper = mc2 and "mcl_core:paper" or "default:paper", + dye_black = mc2 and "mcl_dye:black" or "dye:black", + string = mc2 and "mcl_mobitems:string" or "farming:string", + stick = mc2 and "mcl_core:stick" or "default:stick", + diamond = mc2 and "mcl_core:diamond" or "default:diamond", + steel_ingot = mc2 and "mcl_core:iron_ingot" or "default:steel_ingot", + gold_block = mc2 and "mcl_core:goldblock" or "default:goldblock", + diamond_block = mc2 and "mcl_core:diamondblock" or "default:diamondblock", + stone = mc2 and "mcl_core:stone" or "default:stone", + mese_crystal = mc2 and "mcl_core:gold_ingot" or "default:mese_crystal", + wood = mc2 and "mcl_core:wood" or "default:wood", + fence_wood = mc2 and "group:fence_wood" or "default:fence_wood", + meat_raw = mc2 and "mcl_mobitems:beef" or "group:food_meat_raw", + meat_cooked = mc2 and "mcl_mobitems:cooked_beef" or "group:food_meat", +} -- name tag minetest.register_craftitem("mobs:nametag", { @@ -8,12 +27,12 @@ minetest.register_craftitem("mobs:nametag", { groups = {flammable = 2, nametag = 1} }) -if minetest.get_modpath("dye") and minetest.get_modpath("farming") then - minetest.register_craft({ - output = "mobs:nametag", - recipe = {{"default:paper", "dye:black", "farming:string"}} - }) -end +minetest.register_craft({ + output = "mobs:nametag", + recipe = { + { items.paper, items.dye_black, items.string } + } +}) -- leather minetest.register_craftitem("mobs:leather", { @@ -52,17 +71,14 @@ minetest.register_tool("mobs:lasso", { groups = {flammable = 2} }) -if minetest.get_modpath("farming") then - - minetest.register_craft({ - output = "mobs:lasso", - recipe = { - {"farming:string", "", "farming:string"}, - {"", "default:diamond", ""}, - {"farming:string", "", "farming:string"} - } - }) -end +minetest.register_craft({ + output = "mobs:lasso", + recipe = { + { items.string, "", items.string}, + { "", items.diamond, "" }, + { items.string, "", items.string } + } +}) minetest.register_alias("mobs:magic_lasso", "mobs:lasso") @@ -73,17 +89,14 @@ minetest.register_tool("mobs:net", { groups = {flammable = 2} }) -if minetest.get_modpath("farming") then - - minetest.register_craft({ - output = "mobs:net", - recipe = { - {"group:stick", "", "group:stick"}, - {"group:stick", "", "group:stick"}, - {"farming:string", "group:stick", "farming:string"} - } - }) -end +minetest.register_craft({ + output = "mobs:net", + recipe = { + { items.stick, "", items.stick }, + { items.stick, "", items.stick }, + { items.string, items.stick, items.string } + } +}) -- shears (right click to shear animal) minetest.register_tool("mobs:shears", { @@ -95,8 +108,8 @@ minetest.register_tool("mobs:shears", { minetest.register_craft({ output = "mobs:shears", recipe = { - {"", "default:steel_ingot", ""}, - {"", "group:stick", "default:steel_ingot"} + { "", items.steel_ingot, "" }, + { "", items.stick, items.steel_ingot } } }) @@ -110,9 +123,9 @@ minetest.register_craftitem("mobs:protector", { minetest.register_craft({ output = "mobs:protector", recipe = { - {"default:stone", "default:stone", "default:stone"}, - {"default:stone", "default:goldblock", "default:stone"}, - {"default:stone", "default:stone", "default:stone"} + { items.stone, items.stone, items.stone }, + { items.stone, items.gold_block, items.stone }, + { items.stone, items.stone, items.stone } } }) @@ -126,9 +139,9 @@ minetest.register_craftitem("mobs:protector2", { minetest.register_craft({ output = "mobs:protector2", recipe = { - {"mobs:protector", "default:mese_crystal", "mobs:protector"}, - {"default:mese_crystal", "default:diamondblock", "default:mese_crystal"}, - {"mobs:protector", "default:mese_crystal", "mobs:protector"} + { "mobs:protector", items.mese_crystal, "mobs:protector" }, + { items.mese_crystal, items.diamond_block, items.mese_crystal }, + { "mobs:protector", items.mese_crystal, "mobs:protector" } } }) @@ -143,8 +156,8 @@ minetest.register_craft({ output = "mobs:saddle", recipe = { {"mobs:leather", "mobs:leather", "mobs:leather"}, - {"mobs:leather", "default:steel_ingot", "mobs:leather"}, - {"mobs:leather", "default:steel_ingot", "mobs:leather"} + {"mobs:leather", items.steel_ingot, "mobs:leather"}, + {"mobs:leather", items.steel_ingot, "mobs:leather"} } }) @@ -197,7 +210,7 @@ minetest.register_craft({ output = "mobs:fence_top 12", recipe = { {"group:wood", "group:wood", "group:wood"}, - {"", "default:fence_wood", ""} + {"", items.fence_wood, ""} } }) @@ -372,9 +385,9 @@ minetest.register_node("mobs:meatblock", { minetest.register_craft({ output = "mobs:meatblock", recipe = { - {"group:food_meat", "group:food_meat", "group:food_meat"}, - {"group:food_meat", "group:food_meat", "group:food_meat"}, - {"group:food_meat", "group:food_meat", "group:food_meat"} + { items.meat_cooked, items.meat_cooked, items.meat_cooked }, + { items.meat_cooked, items.meat_cooked, items.meat_cooked }, + { items.meat_cooked, items.meat_cooked, items.meat_cooked } } }) @@ -392,9 +405,9 @@ minetest.register_node("mobs:meatblock_raw", { minetest.register_craft({ output = "mobs:meatblock_raw", recipe = { - {"group:food_meat_raw", "group:food_meat_raw", "group:food_meat_raw"}, - {"group:food_meat_raw", "group:food_meat_raw", "group:food_meat_raw"}, - {"group:food_meat_raw", "group:food_meat_raw", "group:food_meat_raw"} + { items.meat_raw, items.meat_raw, items.meat_raw }, + { items.meat_raw, items.meat_raw, items.meat_raw }, + { items.meat_raw, items.meat_raw, items.meat_raw } } }) diff --git a/init.lua b/init.lua index 4632238..6539b12 100644 --- a/init.lua +++ b/init.lua @@ -7,6 +7,12 @@ minetest.register_privilege("peaceful_player", { give_to_singleplayer = false }) +-- global +mobs = {} + +-- Compatibility +dofile(path .. "/compatibility.lua") + -- Mob API dofile(path .. "/api.lua") diff --git a/mount.lua b/mount.lua index 88cbcd0..4404bd8 100644 --- a/mount.lua +++ b/mount.lua @@ -1,7 +1,19 @@ -- lib_mount by Blert2112 (edited by TenPlus1) -local is_50 = minetest.get_modpath("player_api") -- 5.x compatibility +-- one of these is needed (for now) to ride mobs, otherwise no riding for you +if not minetest.get_modpath("default") +or not minetest.get_modpath("player_api") then + function mobs.attach() end + function mobs.detach() end + function mobs.fly() end + function mobs.drive() end + + return +end + + +local is_50 = minetest.get_modpath("player_api") -- 5.x compatibility local abs, cos, floor, sin, sqrt, pi = math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi diff --git a/readme.MD b/readme.MD index ef69acb..51d406d 100644 --- a/readme.MD +++ b/readme.MD @@ -34,6 +34,7 @@ https://forum.minetest.net/viewtopic.php?f=11&t=9917 * Many bug fixes and tweaks to improve performance * Added 'mobs_attack_creatura' setting so that monsters can attack Creatura mobs * Nodes can be added to 'runaway_from' table +* Better Mineclone2 compatibility with api, items and recipes ### Version 1.56 From e2ee5c62c7d1f7814ad449bab16ac345c8e9fff8 Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Wed, 26 Jul 2023 14:15:03 +0100 Subject: [PATCH 5/7] tidy compat --- api.lua | 13 +++++++++---- compatibility.lua | 10 ---------- init.lua | 5 ----- 3 files changed, 9 insertions(+), 19 deletions(-) delete mode 100644 compatibility.lua diff --git a/api.lua b/api.lua index 9be3d1d..9a25458 100644 --- a/api.lua +++ b/api.lua @@ -23,10 +23,15 @@ end -- CMI support check local use_cmi = minetest.global_exists("cmi") -mobs.mod = "redo" -mobs.version = "20230726" -mobs.intllib = S -mobs.invis = minetest.global_exists("invisibility") and invisibility or {} +mobs = { + mod = "redo", + version = "20230726", + intllib = S, + invis = minetest.global_exists("invisibility") and invisibility or {}, + node_snow = minetest.registered_aliases["mapgen_snow"] or "mcl_core:snow", + node_dirt = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" +} +mobs.fallback_node = mobs.node_dirt -- localize common functions diff --git a/compatibility.lua b/compatibility.lua deleted file mode 100644 index d863098..0000000 --- a/compatibility.lua +++ /dev/null @@ -1,10 +0,0 @@ - -local mc2 = minetest.get_modpath("mcl_core") - -mobs.node_ice = minetest.registered_aliases["mapgen_ice"] or "mcl_core:ice" -mobs.node_snow = minetest.registered_aliases["mapgen_snow"] or "mcl_core:snow" -mobs.node_snowblock = minetest.registered_aliases["mapgen_snowblock"] or "mcl_core:snowblock" -mobs.node_stone = minetest.registered_aliases["mapgen_stone"] or "mcl_core:stone" -mobs.node_dirt = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" - -mobs.fallback_node = mobs.node_dirt diff --git a/init.lua b/init.lua index 6539b12..0205b39 100644 --- a/init.lua +++ b/init.lua @@ -7,11 +7,6 @@ minetest.register_privilege("peaceful_player", { give_to_singleplayer = false }) --- global -mobs = {} - --- Compatibility -dofile(path .. "/compatibility.lua") -- Mob API dofile(path .. "/api.lua") From 07dce8208bb2a60aba87771e6b1e7582741c4475 Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Wed, 26 Jul 2023 17:43:40 +0100 Subject: [PATCH 6/7] harden is_player checks --- api.lua | 41 +++++++++++++++++++++++++---------------- mount.lua | 11 ++++++++++- spawner.lua | 13 +++++++++++-- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/api.lua b/api.lua index 9a25458..3599fb4 100644 --- a/api.lua +++ b/api.lua @@ -260,6 +260,15 @@ local get_distance = function(a, b) end +-- are we a real player ? +local function is_player(player) + + if player and type(player) == "userdata" and minetest.is_player(player) then + return true + end +end + + -- collision function based on jordan4ibanez' open_ai mod function mob_class:collision() @@ -270,7 +279,7 @@ function mob_class:collision() for _,object in ipairs(minetest.get_objects_inside_radius(pos, width)) do - if object:is_player() then + if is_player(object) then local pos2 = object:get_pos() local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} @@ -800,7 +809,7 @@ function mob_class:item_drop() -- was mob killed by player? local death_by_player = self.cause_of_death and self.cause_of_death.puncher - and self.cause_of_death.puncher:is_player() + and is_player(self.cause_of_death.puncher) -- check for tool 'looting_level' under tool_capabilities as default, or use -- meta string 'looting_level' if found (max looting level is 3). @@ -1954,7 +1963,7 @@ function mob_class:general_attack() local ent = objs[n]:get_luaentity() -- are we a player? - if objs[n]:is_player() then + if is_player(objs[n]) then -- if player invisible or mob cannot attack then remove from list if not damage_enabled @@ -2052,7 +2061,7 @@ function mob_class:do_runaway_from() -- loop through entities surrounding mob for n = 1, #objs do - if objs[n]:is_player() then + if is_player(objs[n]) then pname = objs[n]:get_player_name() @@ -2156,7 +2165,7 @@ function mob_class:follow_flop() end else -- stop following player if not holding specific item or mob is horny - if self.following and self.following:is_player() + if self.following and is_player(self.following) and (self:follow_holding(self.following) == false or self.horny) then self.following = nil end @@ -2169,7 +2178,7 @@ function mob_class:follow_flop() local s = self.object:get_pos() local p - if self.following:is_player() then + if is_player(self.following) then p = self.following:get_pos() elseif self.following.object then p = self.following.object:get_pos() @@ -2316,7 +2325,7 @@ function mob_class:do_states(dtime) for n = 1, #objs do - if objs[n]:is_player() then + if is_player(objs[n]) then lp = objs[n]:get_pos() break end @@ -2428,7 +2437,7 @@ function mob_class:do_states(dtime) or not self.attack or not self.attack:get_pos() or self.attack:get_hp() <= 0 - or (self.attack:is_player() + or (is_player(self.attack) and is_invisible(self, self.attack:get_player_name())) then --print(" ** stop attacking **", self.name, self.health, dist, self.view_range) @@ -2819,7 +2828,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage) if self.protected then -- did player hit mob and if so is it in protected area - if hitter:is_player() then + if is_player(hitter) then local player_name = hitter:get_player_name() @@ -2880,7 +2889,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage) -- check if hit by player item or entity local hit_item = weapon_def.name - if not hitter:is_player() then + if not is_player(hitter) then hit_item = hitter:get_luaentity().name end @@ -2987,7 +2996,7 @@ function mob_class:on_punch(hitter, tflp, tool_capabilities, dir, damage) local entity = hitter and hitter:get_luaentity() -- check if arrow from same mob, if so then do no damage - if (entity and entity.name ~= self.arrow) or hitter:is_player() then + if (entity and entity.name ~= self.arrow) or is_player(hitter) then self.health = self.health - floor(damage) end end @@ -3350,7 +3359,7 @@ function mob_class:mob_expire(pos, dtime) for n = 1, #objs do - if objs[n]:is_player() then + if is_player(objs[n]) then self.lifetimer = 20 @@ -3730,7 +3739,7 @@ local function count_mobs(pos, type) for n = 1, #objs do - if not objs[n]:is_player() then + if not is_player(objs[n]) then ent = objs[n]:get_luaentity() @@ -4052,7 +4061,7 @@ function mobs:spawn_specific(name, nodes, neighbors, min_light, max_light, inter for n = 1, #objs do - if objs[n]:is_player() then + if is_player(objs[n]) then --print("--- player too close", name) return end @@ -4248,7 +4257,7 @@ function mobs:register_arrow(name, def) for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.0)) do - if self.hit_player and player:is_player() then + if self.hit_player and is_player(player) then self:hit_player(player) @@ -4496,7 +4505,7 @@ end function mobs:capture_mob( self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) - if not self or not clicker:is_player() or not clicker:get_inventory() then + if not self or not is_player(clicker) or not clicker:get_inventory() then return false end diff --git a/mount.lua b/mount.lua index 4404bd8..4b23373 100644 --- a/mount.lua +++ b/mount.lua @@ -174,6 +174,15 @@ local function find_free_pos(pos) end +-- are we a real player ? +local function is_player(player) + + if player and type(player) == "userdata" and minetest.is_player(player) then + return true + end +end + + function mobs.attach(entity, player) entity.player_rotation = entity.player_rotation or {x = 0, y = 0, z = 0} @@ -212,7 +221,7 @@ function mobs.attach(entity, player) minetest.after(0.2, function() - if player and player:is_player() then + if is_player(player) then if is_50 then player_api.set_animation(player, "sit", 30) diff --git a/spawner.lua b/spawner.lua index bfcdcba..4840d1c 100644 --- a/spawner.lua +++ b/spawner.lua @@ -1,8 +1,17 @@ local S = mobs.intllib --- mob spawner +-- are we a real player ? +local function is_player(player) + + if player and type(player) == "userdata" and minetest.is_player(player) then + return true + end +end + + +-- mob spawner local spawner_default = "mobs_animal:pumba 10 15 0 0 0" minetest.register_node("mobs:spawner", { @@ -148,7 +157,7 @@ minetest.register_abm({ for _, oir in pairs(objsp) do - if oir:is_player() then + if is_player(oir) then in_range = 1 From 8201c165e794751abdd6d9e428635c93bc839c7e Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Thu, 27 Jul 2023 12:54:46 +0100 Subject: [PATCH 7/7] can now ride mobs redo mobs in mineclone2 --- mount.lua | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/mount.lua b/mount.lua index 4b23373..296b63f 100644 --- a/mount.lua +++ b/mount.lua @@ -1,6 +1,6 @@ -- lib_mount by Blert2112 (edited by TenPlus1) --- one of these is needed (for now) to ride mobs, otherwise no riding for you +--[[ one of these is needed (for now) to ride mobs, otherwise no riding for you if not minetest.get_modpath("default") or not minetest.get_modpath("player_api") then @@ -11,9 +11,11 @@ or not minetest.get_modpath("player_api") then return end - +]] local is_50 = minetest.get_modpath("player_api") -- 5.x compatibility +local is_mc2 = minetest.get_modpath("mcl_mobs") -- MineClone2 compatibility + local abs, cos, floor, sin, sqrt, pi = math.abs, math.cos, math.floor, math.sin, math.sqrt, math.pi @@ -87,9 +89,7 @@ end local function force_detach(player) - if not player then return end - - local attached_to = player:get_attach() + local attached_to = player and player:get_attach() if not attached_to then return @@ -97,8 +97,7 @@ local function force_detach(player) local entity = attached_to:get_luaentity() - if entity and entity.driver - and entity.driver == player then + if entity and entity.driver and entity.driver == player then entity.driver = nil end @@ -109,6 +108,9 @@ local function force_detach(player) if is_50 then player_api.player_attached[name] = false player_api.set_animation(player, "stand", 30) + elseif is_mc2 then + mcl_player.player_attached[player:get_player_name()] = false + mcl_player.player_set_animation(player, "stand", 30) else default.player_attached[name] = false default.player_set_animation(player, "stand", 30) @@ -163,8 +165,7 @@ local function find_free_pos(pos) local def = minetest.registered_nodes[node.name] - if def and not def.walkable and - def.liquidtype == "none" then + if def and not def.walkable and def.liquidtype == "none" then return npos end end @@ -205,6 +206,8 @@ function mobs.attach(entity, player) if is_50 then player_api.player_attached[player:get_player_name()] = true + elseif is_mc2 then + mcl_player.player_attached[player:get_player_name()] = true else default.player_attached[player:get_player_name()] = true end @@ -225,6 +228,8 @@ function mobs.attach(entity, player) if is_50 then player_api.set_animation(player, "sit", 30) + elseif is_mc2 then + mcl_player.player_set_animation(player, "sit_mount" , 30) else default.player_set_animation(player, "sit", 30) end @@ -272,13 +277,11 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) local ctrl = entity.driver:get_player_control() - -- move forwards - if ctrl.up then + if ctrl.up then -- move forwards entity.v = entity.v + entity.accel * dtime - -- move backwards - elseif ctrl.down then + elseif ctrl.down then -- move backwards if entity.max_speed_reverse == 0 and entity.v == 0 then return @@ -308,8 +311,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) if can_fly then - -- fly up - if ctrl.jump then + if ctrl.jump then -- fly up velo.y = velo.y + 1 @@ -322,8 +324,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) if velo.y < 0 then velo.y = 0 end end - -- fly down - if ctrl.sneak then + if ctrl.sneak then -- fly down velo.y = velo.y - 1 @@ -336,8 +337,7 @@ function mobs.drive(entity, moving_anim, stand_anim, can_fly, dtime) if velo.y > 0 then velo.y = 0 end end else - -- jump - if ctrl.jump then + if ctrl.jump then -- jump if velo.y == 0 then velo.y = velo.y + entity.jump_height @@ -470,12 +470,10 @@ end function mobs.fly(entity, _, speed, shoots, arrow, moving_anim, stand_anim) local ctrl = entity.driver:get_player_control() ; if not ctrl then return end - local velo = entity.object:get_velocity() + local velo = entity.object:get_velocity() ; if not velo then return end local dir = entity.driver:get_look_dir() local yaw = entity.driver:get_look_horizontal() + 1.57 - if not ctrl or not velo then return end - if ctrl.up then entity.object:set_velocity({