From 725dc731ddc2a6f1cf1a20832e06883613d5974a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 11 Apr 2021 11:58:33 -0400 Subject: [PATCH 001/117] Adjust mob collision detection - this breaks a lot of things and will be fixed later --- mods/ENTITIES/mcl_mobs/api.lua | 142 ++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 6c1a0567ec..ad60a508db 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -210,7 +210,21 @@ local do_attack = function(self, player) end + + +------------------------------------------------------------------------------------------------------------------------------------ + + + + + + + + + + -- collision function borrowed amended from jordan4ibanez open_ai mod +--[[ local collision = function(self) local pos = self.object:get_pos() @@ -237,6 +251,120 @@ local collision = function(self) return({x,z}) end +]]-- + +local collision = function(self) + pos = self.object:get_pos() + --do collision detection from the base of the mob + + collisionbox = self.object:get_properties().collisionbox + + pos.y = pos.y + collisionbox[2] + + collision_boundary = collisionbox[4] + + radius = collision_boundary + + if collisionbox[5] > collision_boundary then + radius = collisionbox[5] + end + + collision_count = 0 + + for _,object in ipairs(minetest.get_objects_inside_radius(pos, radius*1.25)) do + if object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) and + --don't collide with rider, rider don't collide with thing + (not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and + (not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then + --stop infinite loop + collision_count = collision_count + 1 + if collision_count > 100 then + break + end + pos2 = object:get_pos() + + object_collisionbox = object:get_properties().collisionbox + + pos2.y = pos2.y + object_collisionbox[2] + + object_collision_boundary = object_collisionbox[4] + + + --this is checking the difference of the object collided with's possision + --if positive top of other object is inside (y axis) of current object + y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y + + y_top_diff = (pos.y + collisionbox[5]) - pos2.y + + + distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)) + + if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then + + dir = vector.direction(pos,pos2) + dir.y = 0 + + --eliminate mob being stuck in corners + if dir.x == 0 and dir.z == 0 then + dir = vector.new(math.random(-1,1)*math.random(),0,math.random(-1,1)*math.random()) + end + + local velocity = vector.multiply(dir,1.1) + + --local velocity = vector.normalize(dir) + + vel1 = vector.multiply(velocity, -1) + vel2 = velocity + + self.object:add_velocity(vel1) + + if object:is_player() then + object:add_player_velocity(vel2) + + --if self.on_fire then + -- start_fire(object) + --end + + --if is_player_on_fire(object) then + -- start_fire(self.object) + --end + + else + object:add_velocity(vel2) + --if self.on_fire then + -- start_fire(object) + --end + --if object:get_luaentity().on_fire then + -- start_fire(self.object) + --end + end + end + end + end +end + + + + + + + + + + + + +------------------------------------------------------------------------------------------------------------------------------------ + + + + + + + + + + -- move mob in facing direction local set_velocity = function(self, v) @@ -244,9 +372,9 @@ local set_velocity = function(self, v) local c_x, c_y = 0, 0 -- can mob be pushed, if so calculate direction - if self.pushable then - c_x, c_y = unpack(collision(self)) - end + --if self.pushable then + --c_x, c_y = unpack(collision(self)) + --end -- halt mob if it has been ordered to stay if self.order == "stand" then @@ -256,11 +384,17 @@ local set_velocity = function(self, v) local yaw = (self.object:get_yaw() or 0) + self.rotate - self.object:set_velocity({ + self.object:add_velocity({ x = (sin(yaw) * -v) + c_x, y = self.object:get_velocity().y, z = (cos(yaw) * v) + c_y, }) + + if self.pushable then + --c_x, c_y = unpack(collision(self)) + + collision(self) + end end From 2456e3cd1ef6954415e4a771bb704a12364895eb Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 11 Apr 2021 12:52:31 -0400 Subject: [PATCH 002/117] Adjust math localizations in api.lua --- mods/ENTITIES/mcl_mobs/api.lua | 235 ++++++++++++++++----------------- 1 file changed, 115 insertions(+), 120 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index ad60a508db..37a1cc4732 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1,9 +1,23 @@ +-- API for Mobs Redo: MineClone 2 Delux 2.0 DRM Free Early Access Super Extreme Edition + +-- current state of things: "why are these not in the same table as those?", and, "why are these not localized?" + +-- lua locals + +-- localize math functions +local math_pi = math.pi +local math_sin = math.sin +local math_cos = math.cos +local math_abs = math.abs +local math_min = math.min +local math_max = math.max +local math_atan = math.atan +local math_random = math.random +local math_floor = math.floor + --- API for Mobs Redo: MineClone 2 Edition (MRM) mobs = {} -mobs.mod = "mrm" -mobs.version = "20210106" -- don't rely too much on this, rarely updated, if ever local MAX_MOB_NAME_LENGTH = 30 local HORNY_TIME = 30 @@ -40,21 +54,13 @@ function mobs.is_creative(name) end --- localize math functions -local pi = math.pi -local sin = math.sin -local cos = math.cos -local abs = math.abs -local min = math.min -local max = math.max -local atann = math.atan -local random = math.random -local floor = math.floor + + local atan = function(x) if not x or x ~= x then return 0 else - return atann(x) + return math_atan(x) end end @@ -157,7 +163,7 @@ local mob_sound = function(self, soundname, is_opinion, fixed_pitch) pitch = base_pitch end -- randomize the pitch a bit - pitch = pitch + math.random(-10, 10) * 0.005 + pitch = pitch + math_random(-10, 10) * 0.005 end minetest.sound_play(sound, { object = self.object, @@ -204,7 +210,7 @@ local do_attack = function(self, player) self.state = "attack" -- TODO: Implement war_cry sound without being annoying - --if random(0, 100) < 90 then + --if math_random(0, 100) < 90 then --mob_sound(self, "war_cry", true) --end end @@ -306,7 +312,7 @@ local collision = function(self) --eliminate mob being stuck in corners if dir.x == 0 and dir.z == 0 then - dir = vector.new(math.random(-1,1)*math.random(),0,math.random(-1,1)*math.random()) + dir = vector.new(math_random(-1,1)*math_random(),0,math_random(-1,1)*math_random()) end local velocity = vector.multiply(dir,1.1) @@ -385,9 +391,9 @@ local set_velocity = function(self, v) local yaw = (self.object:get_yaw() or 0) + self.rotate self.object:add_velocity({ - x = (sin(yaw) * -v) + c_x, + x = (math_sin(yaw) * -v) + c_x, y = self.object:get_velocity().y, - z = (cos(yaw) * v) + c_y, + z = (math_cos(yaw) * v) + c_y, }) if self.pushable then @@ -415,13 +421,13 @@ local function update_roll(self) local was_Fleckenstein = false local rot = self.object:get_rotation() - rot.z = is_Fleckenstein and pi or 0 + rot.z = is_Fleckenstein and math_pi or 0 self.object:set_rotation(rot) local cbox = table.copy(self.collisionbox) local acbox = self.object:get_properties().collisionbox - if math.abs(cbox[2] - acbox[2]) > 0.1 then + if math_abs(cbox[2] - acbox[2]) > 0.1 then was_Fleckenstein = true end @@ -449,7 +455,7 @@ local set_yaw = function(self, yaw, delay, dtime) if delay == 0 then if self.shaking and dtime then - yaw = yaw + (math.random() * 2 - 1) * 5 * dtime + yaw = yaw + (math_random() * 2 - 1) * 5 * dtime end self.object:set_yaw(yaw) update_roll(self) @@ -718,7 +724,7 @@ local damage_effect = function(self, damage) -- damage particles if (not disable_blood) and damage > 0 then - local amount_large = math.floor(damage / 2) + local amount_large = math_floor(damage / 2) local amount_small = damage % 2 local pos = self.object:get_pos() @@ -748,8 +754,8 @@ mobs.death_effect = function(pos, yaw, collisionbox, rotate) max = { x = 0.5, y = 0.5, z = 0.5 } end if rotate then - min = vector.rotate(min, {x=0, y=yaw, z=pi/2}) - max = vector.rotate(max, {x=0, y=yaw, z=pi/2}) + min = vector.rotate(min, {x=0, y=yaw, z=math_pi/2}) + max = vector.rotate(max, {x=0, y=yaw, z=math_pi/2}) min, max = vector.sort(min, max) min = vector.multiply(min, 0.5) max = vector.multiply(max, 0.5) @@ -837,14 +843,14 @@ local item_drop = function(self, cooked, looting_level) local num = 0 local do_common_looting = (looting_level > 0 and looting_type == "common") - if random() < chance then - num = random(dropdef.min or 1, dropdef.max or 1) + if math_random() < chance then + num = math_random(dropdef.min or 1, dropdef.max or 1) elseif not dropdef.looting_ignore_chance then do_common_looting = false end if do_common_looting then - num = num + math.floor(math.random(0, looting_level) + 0.5) + num = num + math_floor(math_random(0, looting_level) + 0.5) end if num > 0 then @@ -869,9 +875,9 @@ local item_drop = function(self, cooked, looting_level) if obj and obj:get_luaentity() then obj:set_velocity({ - x = random(-10, 10) / 9, + x = math_random(-10, 10) / 9, y = 6, - z = random(-10, 10) / 9, + z = math_random(-10, 10) / 9, }) elseif obj then obj:remove() -- item does not exist @@ -953,7 +959,7 @@ local check_for_death = function(self, cause, cmi_cause) item_drop(self, cooked, looting) if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then - mcl_experience.throw_experience(self.object:get_pos(), math.random(self.xp_min, self.xp_max)) + mcl_experience.throw_experience(self.object:get_pos(), math_random(self.xp_min, self.xp_max)) end end end @@ -1018,7 +1024,7 @@ local check_for_death = function(self, cause, cmi_cause) set_animation(self, "die") else local rot = self.object:get_rotation() - rot.z = pi/2 + rot.z = math_pi/2 self.object:set_rotation(rot) length = 1 + DEATH_DELAY set_animation(self, "stand", true) @@ -1084,8 +1090,8 @@ local is_at_cliff_or_danger = function(self) return false end local yaw = self.object:get_yaw() - local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) + local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor @@ -1119,8 +1125,8 @@ local is_at_water_danger = function(self) return false end local yaw = self.object:get_yaw() - local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) + local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor @@ -1337,7 +1343,7 @@ local do_env_damage = function(self) end if drowning then - self.breath = math.max(0, self.breath - 1) + self.breath = math_max(0, self.breath - 1) effect(pos, 2, "bubble.png", nil, nil, 1, nil) if self.breath <= 0 then @@ -1355,7 +1361,7 @@ local do_env_damage = function(self) return true end else - self.breath = math.min(self.breath_max, self.breath + 1) + self.breath = math_min(self.breath_max, self.breath + 1) end end @@ -1426,8 +1432,8 @@ local do_jump = function(self) end -- where is front - local dir_x = -sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = cos(yaw) * (self.collisionbox[4] + 0.5) + local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) -- what is in front of mob? nod = node_ok({ @@ -1527,7 +1533,7 @@ local entity_physics = function(pos, radius) dist = vector.distance(pos, obj_pos) if dist < 1 then dist = 1 end - local damage = floor((4 / dist) * radius) + local damage = math_floor((4 / dist) * radius) local ent = objs[n]:get_luaentity() -- punches work on entities AND players @@ -1682,7 +1688,7 @@ local breed = function(self) -- Give XP if mod_experience then - mcl_experience.throw_experience(pos, math.random(1, 7)) + mcl_experience.throw_experience(pos, math_random(1, 7)) end -- custom breed function @@ -1699,7 +1705,7 @@ local breed = function(self) -- Use texture of one of the parents - local p = math.random(1, 2) + local p = math_random(1, 2) if p == 1 then ent_c.base_texture = parent1.base_texture else @@ -1730,7 +1736,7 @@ local replace = function(self, pos) or not self.replace_what or self.child == true or self.object:get_velocity().y ~= 0 - or random(1, self.replace_rate) > 1 then + or math_random(1, self.replace_rate) > 1 then return end @@ -1738,7 +1744,7 @@ local replace = function(self, pos) if type(self.replace_what[1]) == "table" then - local num = random(#self.replace_what) + local num = math_random(#self.replace_what) what = self.replace_what[num][1] or "" with = self.replace_what[num][2] or "" @@ -1800,7 +1806,7 @@ local smart_mobs = function(self, s, p, dist, dtime) local target_pos = self.attack:get_pos() -- is it becoming stuck? - if abs(s1.x - s.x) + abs(s1.z - s.z) < .5 then + if math_abs(s1.x - s.x) + math_abs(s1.z - s.z) < .5 then self.path.stuck_timer = self.path.stuck_timer + dtime else self.path.stuck_timer = 0 @@ -1861,7 +1867,7 @@ local smart_mobs = function(self, s, p, dist, dtime) end, self) end - if math.abs(vector.subtract(s,target_pos).y) > self.stepheight then + if math_abs(vector.subtract(s,target_pos).y) > self.stepheight then if height_switcher then use_pathfind = true @@ -1881,8 +1887,8 @@ local smart_mobs = function(self, s, p, dist, dtime) -- round position to center of node to avoid stuck in walls -- also adjust height for player models! - s.x = floor(s.x + 0.5) - s.z = floor(s.z + 0.5) + s.x = math_floor(s.x + 0.5) + s.z = math_floor(s.z + 0.5) local ssight, sground = minetest.line_of_sight(s, { x = s.x, y = s.y - 4, z = s.z}, 1) @@ -1894,9 +1900,9 @@ local smart_mobs = function(self, s, p, dist, dtime) local p1 = self.attack:get_pos() - p1.x = floor(p1.x + 0.5) - p1.y = floor(p1.y + 0.5) - p1.z = floor(p1.z + 0.5) + p1.x = math_floor(p1.x + 0.5) + p1.y = math_floor(p1.y + 0.5) + p1.z = math_floor(p1.z + 0.5) local dropheight = 12 if self.fear_height ~= 0 then dropheight = self.fear_height end @@ -1962,11 +1968,11 @@ local smart_mobs = function(self, s, p, dist, dtime) else -- dig 2 blocks to make door toward player direction - local yaw1 = self.object:get_yaw() + pi / 2 + local yaw1 = self.object:get_yaw() + math_pi / 2 local p1 = { - x = s.x + cos(yaw1), + x = s.x + math_cos(yaw1), y = s.y, - z = s.z + sin(yaw1) + z = s.z + math_sin(yaw1) } if not minetest.is_protected(p1, "") then @@ -2244,10 +2250,10 @@ local runaway_from = function(self) z = lp.z - s.z } - local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate + local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate if lp.x > s.x then - yaw = yaw + pi + yaw = yaw + math_pi end yaw = set_yaw(self, yaw, 4) @@ -2336,9 +2342,9 @@ local follow_flop = function(self) z = p.z - s.z } - local yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + local yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + pi end + if p.x > s.x then yaw = yaw + math_pi end set_yaw(self, yaw, 2.35) @@ -2374,9 +2380,9 @@ local follow_flop = function(self) if sdef and sdef.walkable then mob_sound(self, "flop") self.object:set_velocity({ - x = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + x = math_random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), y = FLOP_HEIGHT, - z = math.random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + z = math_random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), }) end @@ -2428,7 +2434,7 @@ local do_states = function(self, dtime) if self.state == "stand" then - if random(1, 4) == 1 then + if math_random(1, 4) == 1 then local lp = nil local s = self.object:get_pos() @@ -2450,11 +2456,11 @@ local do_states = function(self, dtime) z = lp.z - s.z } - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - if lp.x > s.x then yaw = yaw + pi end + if lp.x > s.x then yaw = yaw + math_pi end else - yaw = yaw + random(-0.5, 0.5) + yaw = yaw + math_random(-0.5, 0.5) end yaw = set_yaw(self, yaw, 8) @@ -2469,7 +2475,7 @@ local do_states = function(self, dtime) if self.walk_chance ~= 0 and self.facing_fence ~= true - and random(1, 100) <= self.walk_chance + and math_random(1, 100) <= self.walk_chance and is_at_cliff_or_danger(self) == false then set_velocity(self, self.walk_velocity) @@ -2519,7 +2525,7 @@ local do_states = function(self, dtime) {x = s.x + 5, y = s.y + 1, z = s.z + 5}, {"group:solid"}) - lp = #lp > 0 and lp[random(#lp)] + lp = #lp > 0 and lp[math_random(#lp)] -- did we find land? if lp then @@ -2529,10 +2535,10 @@ local do_states = function(self, dtime) z = lp.z - s.z } - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - if lp.x > s.x then yaw = yaw + pi end + if lp.x > s.x then yaw = yaw + math_pi end -- look towards land and move in that direction yaw = set_yaw(self, yaw, 6) @@ -2545,8 +2551,8 @@ local do_states = function(self, dtime) else -- Randomly turn - if random(1, 100) <= 30 then - yaw = yaw + random(-0.5, 0.5) + if math_random(1, 100) <= 30 then + yaw = yaw + math_random(-0.5, 0.5) yaw = set_yaw(self, yaw, 8) end end @@ -2554,9 +2560,9 @@ local do_states = function(self, dtime) yaw = set_yaw(self, yaw, 8) -- otherwise randomly turn - elseif random(1, 100) <= 30 then + elseif math_random(1, 100) <= 30 then - yaw = yaw + random(-0.5, 0.5) + yaw = yaw + math_random(-0.5, 0.5) yaw = set_yaw(self, yaw, 8) end @@ -2567,7 +2573,7 @@ local do_states = function(self, dtime) end if self.facing_fence == true or cliff_or_danger - or random(1, 100) <= 30 then + or math_random(1, 100) <= 30 then set_velocity(self, 0) self.state = "stand" @@ -2642,9 +2648,9 @@ local do_states = function(self, dtime) z = p.z - s.z } - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + pi end + if p.x > s.x then yaw = yaw + math_pi end yaw = set_yaw(self, yaw, 0, dtime) @@ -2738,9 +2744,9 @@ local do_states = function(self, dtime) and dist > self.reach then local p1 = s - local me_y = floor(p1.y) + local me_y = math_floor(p1.y) local p2 = p - local p_y = floor(p2.y + 1) + local p_y = math_floor(p2.y + 1) local v = self.object:get_velocity() if flight_check(self, s) then @@ -2801,7 +2807,7 @@ local do_states = function(self, dtime) return end - if abs(p1.x-s.x) + abs(p1.z - s.z) < 0.6 then + if math_abs(p1.x-s.x) + math_abs(p1.z - s.z) < 0.6 then -- reached waypoint, remove it from queue table.remove(self.path.way, 1) end @@ -2815,9 +2821,9 @@ local do_states = function(self, dtime) z = p.z - s.z } - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + pi end + if p.x > s.x then yaw = yaw + math_pi end yaw = set_yaw(self, yaw, 0, dtime) @@ -2867,7 +2873,7 @@ local do_states = function(self, dtime) self.timer = 0 if self.double_melee_attack - and random(1, 2) == 1 then + and math_random(1, 2) == 1 then set_animation(self, "punch2") else set_animation(self, "punch") @@ -2920,9 +2926,9 @@ local do_states = function(self, dtime) z = p.z - s.z } - yaw = (atan(vec.z / vec.x) + pi / 2) - self.rotate + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - if p.x > s.x then yaw = yaw + pi end + if p.x > s.x then yaw = yaw + math_pi end yaw = set_yaw(self, yaw, 0, dtime) @@ -2934,7 +2940,7 @@ local do_states = function(self, dtime) if self.shoot_interval and self.timer > self.shoot_interval and not minetest.raycast(p, self.attack:get_pos(), false, false):next() - and random(1, 100) <= 60 then + and math_random(1, 100) <= 60 then self.timer = 0 set_animation(self, "shoot") @@ -3038,7 +3044,7 @@ local falling = function(self, pos) self.object:set_acceleration({ x = 0, - y = -self.fall_speed / (max(1, v.y) ^ 2), + y = -self.fall_speed / (math_max(1, v.y) ^ 2), z = 0 }) end @@ -3057,7 +3063,7 @@ local falling = function(self, pos) if add ~= 0 then damage = damage + damage * (add/100) end - damage = floor(damage) + damage = math_floor(damage) if damage > 0 then self.health = self.health - damage @@ -3171,7 +3177,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) -- healing if damage <= -1 then - self.health = self.health - floor(damage) + self.health = self.health - math_floor(damage) return end @@ -3198,7 +3204,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) local weapon = hitter:get_wielded_item(player) local def = weapon:get_definition() if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then - local wear = floor(65535/tool_capabilities.punch_attack_uses) + local wear = math_floor(65535/tool_capabilities.punch_attack_uses) weapon:add_wear(wear) hitter:set_wielded_item(weapon) end @@ -3214,7 +3220,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) -- weapon sounds if weapon:get_definition().sounds ~= nil then - local s = random(0, #weapon:get_definition().sounds) + local s = math_random(0, #weapon:get_definition().sounds) minetest.sound_play(weapon:get_definition().sounds[s], { object = self.object, --hitter, @@ -3243,7 +3249,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) and tflp >= punch_interval then local v = self.object:get_velocity() - local r = 1.4 - min(punch_interval, 1.4) + local r = 1.4 - math_min(punch_interval, 1.4) local kb = r * 2.0 local up = 2 @@ -3296,10 +3302,10 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) z = lp.z - s.z } - local yaw = (atan(vec.z / vec.x) + 3 * pi / 2) - self.rotate + local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate if lp.x > s.x then - yaw = yaw + pi + yaw = yaw + math_pi end yaw = set_yaw(self, yaw, 6) @@ -3440,7 +3446,7 @@ local mob_activate = function(self, staticdata, def, dtime) def.textures = {def.textures} end - self.base_texture = def.textures[random(1, #def.textures)] + self.base_texture = def.textures[math_random(1, #def.textures)] self.base_mesh = def.mesh self.base_size = self.visual_size self.base_colbox = self.collisionbox @@ -3502,7 +3508,7 @@ local mob_activate = function(self, staticdata, def, dtime) end if self.health == 0 then - self.health = random (self.hp_min, self.hp_max) + self.health = math_random (self.hp_min, self.hp_max) end if self.breath == nil then self.breath = self.breath_max @@ -3555,7 +3561,7 @@ local mob_activate = function(self, staticdata, def, dtime) -- set anything changed above self.object:set_properties(self) - set_yaw(self, (random(0, 360) - 180) / 180 * pi, 6) + set_yaw(self, (math_random(0, 360) - 180) / 180 * math_pi, 6) update_tag(self) set_animation(self, "stand") @@ -3620,12 +3626,12 @@ local mob_step = function(self, dtime) if self.delay == 1 then yaw = self.target_yaw else - local dif = abs(yaw - self.target_yaw) + local dif = math_abs(yaw - self.target_yaw) if yaw > self.target_yaw then - if dif > pi then - dif = 2 * pi - dif -- need to add + if dif > math_pi then + dif = 2 * math_pi - dif -- need to add yaw = yaw + dif / self.delay else yaw = yaw - dif / self.delay -- need to subtract @@ -3633,21 +3639,21 @@ local mob_step = function(self, dtime) elseif yaw < self.target_yaw then - if dif > pi then - dif = 2 * pi - dif + if dif > math_pi then + dif = 2 * math_pi - dif yaw = yaw - dif / self.delay -- need to subtract else yaw = yaw + dif / self.delay -- need to add end end - if yaw > (pi * 2) then yaw = yaw - (pi * 2) end - if yaw < 0 then yaw = yaw + (pi * 2) end + if yaw > (math_pi * 2) then yaw = yaw - (math_pi * 2) end + if yaw < 0 then yaw = yaw + (math_pi * 2) end end self.delay = self.delay - 1 if self.shaking then - yaw = yaw + (math.random() * 2 - 1) * 5 * dtime + yaw = yaw + (math_random() * 2 - 1) * 5 * dtime end self.object:set_yaw(yaw) update_roll(self) @@ -3690,7 +3696,7 @@ local mob_step = function(self, dtime) end -- mob plays random sound at times - if random(1, 70) == 1 then + if math_random(1, 70) == 1 then mob_sound(self, "random", true) end @@ -3730,11 +3736,11 @@ local mob_step = function(self, dtime) runaway_from(self) if is_at_water_danger(self) and self.state ~= "attack" then - if random(1, 10) <= 6 then + if math_random(1, 10) <= 6 then set_velocity(self, 0) self.state = "stand" set_animation(self, "stand") - yaw = yaw + random(-0.5, 0.5) + yaw = yaw + math_random(-0.5, 0.5) yaw = set_yaw(self, yaw, 8) end end @@ -3802,7 +3808,7 @@ local mob_step = function(self, dtime) mcl_burning.extinguish(self.object) self.object:remove() elseif self.lifetimer <= 10 then - if math.random(10) < 4 then + if math_random(10) < 4 then self.despawn_immediately = true else self.lifetimer = 20 @@ -3880,7 +3886,7 @@ local function scale_difficulty(value, default, min, special) if (not value) or (value == default) or (value == special) then return default else - return max(min, value * difficulty) + return math_max(min, value * difficulty) end end @@ -4084,17 +4090,6 @@ function mobs:register_arrow(name, def) on_punch = function(self) local vel = self.object:get_velocity() self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) - end, - collisionbox = def.collisionbox or {0, 0, 0, 0, 0, 0}, - automatic_face_movement_dir = def.rotate - and (def.rotate - (pi / 180)) or false, - - on_activate = def.on_activate, - - on_step = def.on_step or function(self, dtime) - - self.timer = self.timer + 1 - local pos = self.object:get_pos() if self.switch == 0 From 67c40885ef62b4e4e8dcaba3b65c58502c558f7e Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 11 Apr 2021 14:21:19 -0400 Subject: [PATCH 003/117] Fix mobs collision system only running during movement - major overhaul with ai disabled --- mods/ENTITIES/mcl_mobs/api.lua | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 37a1cc4732..e3004d3237 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -374,14 +374,8 @@ end -- move mob in facing direction local set_velocity = function(self, v) - local c_x, c_y = 0, 0 - -- can mob be pushed, if so calculate direction - --if self.pushable then - --c_x, c_y = unpack(collision(self)) - --end - -- halt mob if it has been ordered to stay if self.order == "stand" then self.object:set_velocity({x = 0, y = 0, z = 0}) @@ -395,12 +389,6 @@ local set_velocity = function(self, v) y = self.object:get_velocity().y, z = (math_cos(yaw) * v) + c_y, }) - - if self.pushable then - --c_x, c_y = unpack(collision(self)) - - collision(self) - end end @@ -3587,6 +3575,7 @@ end -- main mob function local mob_step = function(self, dtime) + --[[ if not self.fire_resistant then mcl_burning.tick(self.object, dtime) end @@ -3745,6 +3734,7 @@ local mob_step = function(self, dtime) end end + -- Add water flowing for mobs from mcl_item_entity local p, node, nn, def p = self.object:get_pos() @@ -3756,10 +3746,11 @@ local mob_step = function(self, dtime) -- Move item around on flowing liquids if def and def.liquidtype == "flowing" then - + ]]-- --[[ Get flowing direction (function call from flowlib), if there's a liquid. NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] + --[[ local vec = flowlib.quick_flow(p, node) -- Just to make sure we don't manipulate the speed for no reason if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then @@ -3815,6 +3806,13 @@ local mob_step = function(self, dtime) end end end + ]]-- + + -- can mob be pushed, if so calculate direction + if self.pushable then + --c_x, c_y = unpack(collision(self)) + collision(self) + end end From 9aafc28a2009998017753d0aa4d013e3cd8795b6 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 11 Apr 2021 14:47:56 -0400 Subject: [PATCH 004/117] Fix mobs nil check during mob_step --- mods/ENTITIES/mcl_mobs/api.lua | 29 ++++++++++++++++------------- mods/ENTITIES/mcl_mobs/spawning.lua | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index e3004d3237..fa3e4ad440 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -324,6 +324,8 @@ local collision = function(self) self.object:add_velocity(vel1) + --reenable fire spreading eventually + if object:is_player() then object:add_player_velocity(vel2) @@ -3575,7 +3577,16 @@ end -- main mob function local mob_step = function(self, dtime) - --[[ + if not self or not self.object or not self.object:get_luaentity() then + return false + end + + -- can mob be pushed, if so calculate direction -- do this first to prevent issues + -- you can push mobs when they're in the dead state + if self.pushable then + collision(self) + end + if not self.fire_resistant then mcl_burning.tick(self.object, dtime) end @@ -3598,9 +3609,11 @@ local mob_step = function(self, dtime) if self.jump_sound_cooloff > 0 then self.jump_sound_cooloff = self.jump_sound_cooloff - dtime end + if self.opinion_sound_cooloff > 0 then self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime end + if falling(self, pos) then -- Return if mob died after falling return @@ -3716,9 +3729,7 @@ local mob_step = function(self, dtime) return end - if not self.object:get_luaentity() then - return false - end + do_jump(self) @@ -3746,11 +3757,10 @@ local mob_step = function(self, dtime) -- Move item around on flowing liquids if def and def.liquidtype == "flowing" then - ]]-- + --[[ Get flowing direction (function call from flowlib), if there's a liquid. NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] - --[[ local vec = flowlib.quick_flow(p, node) -- Just to make sure we don't manipulate the speed for no reason if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then @@ -3806,13 +3816,6 @@ local mob_step = function(self, dtime) end end end - ]]-- - - -- can mob be pushed, if so calculate direction - if self.pushable then - --c_x, c_y = unpack(collision(self)) - collision(self) - end end diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/spawning.lua index ff52128dfb..f815d88115 100644 --- a/mods/ENTITIES/mcl_mobs/spawning.lua +++ b/mods/ENTITIES/mcl_mobs/spawning.lua @@ -155,6 +155,7 @@ Overworld regular: local mobs_spawn = minetest.settings:get_bool("mobs_spawn", true) ~= false +mobs_spawn = false -- count how many mobs of one type are inside an area local count_mobs = function(pos,mobtype) From 00759da39d621b36be6200fa365c51be86dbb99f Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 11 Apr 2021 18:29:32 -0400 Subject: [PATCH 005/117] Unlimit mob ai --- mods/ENTITIES/mcl_mobs/api.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index fa3e4ad440..4578f77c54 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -3574,7 +3574,6 @@ local mob_activate = function(self, staticdata, def, dtime) end --- main mob function local mob_step = function(self, dtime) if not self or not self.object or not self.object:get_luaentity() then @@ -3683,14 +3682,17 @@ local mob_step = function(self, dtime) -- attack timer self.timer = self.timer + dtime + --[[ if self.state ~= "attack" then if self.timer < 1 then + print("returning>>error code 1") return end self.timer = 0 end + ]]-- -- never go over 100 if self.timer > 100 then @@ -3729,8 +3731,6 @@ local mob_step = function(self, dtime) return end - - do_jump(self) runaway_from(self) From a564009e4aeda08372b80fb1a5fc2d16f5dfd364 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Mon, 12 Apr 2021 08:11:55 -0400 Subject: [PATCH 006/117] Change HORNY_TIMER to BREED_TIMER --- mods/ENTITIES/mcl_mobs/api.lua | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 4578f77c54..377244a1c0 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -15,13 +15,11 @@ local math_atan = math.atan local math_random = math.random local math_floor = math.floor - - mobs = {} local MAX_MOB_NAME_LENGTH = 30 -local HORNY_TIME = 30 -local HORNY_AGAIN_TIME = 300 +local BREED_TIME = 30 +local BREED_TIME_AGAIN = 300 local CHILD_GROW_TIME = 60*20 local DEATH_DELAY = 0.5 local DEFAULT_FALL_SPEED = -10 @@ -1603,14 +1601,14 @@ local breed = function(self) return end - -- horny animal can mate for HORNY_TIME seconds, - -- afterwards horny animal cannot mate again for HORNY_AGAIN_TIME seconds + -- horny animal can mate for BREED_TIME seconds, + -- afterwards horny animal cannot mate again for BREED_TIME_AGAIN seconds if self.horny == true - and self.hornytimer < HORNY_TIME + HORNY_AGAIN_TIME then + and self.hornytimer < BREED_TIME + BREED_TIME_AGAIN then self.hornytimer = self.hornytimer + 1 - if self.hornytimer >= HORNY_TIME + HORNY_AGAIN_TIME then + if self.hornytimer >= BREED_TIME + BREED_TIME_AGAIN then self.hornytimer = 0 self.horny = false end @@ -1618,7 +1616,7 @@ local breed = function(self) -- find another same animal who is also horny and mate if nearby if self.horny == true - and self.hornytimer <= HORNY_TIME then + and self.hornytimer <= BREED_TIME then local pos = self.object:get_pos() @@ -1657,15 +1655,15 @@ local breed = function(self) if ent and canmate == true and ent.horny == true - and ent.hornytimer <= HORNY_TIME then + and ent.hornytimer <= BREED_TIME then num = num + 1 end -- found your mate? then have a baby if num > 1 then - self.hornytimer = HORNY_TIME + 1 - ent.hornytimer = HORNY_TIME + 1 + self.hornytimer = BREED_TIME + 1 + ent.hornytimer = BREED_TIME + 1 -- spawn baby minetest.after(5, function(parent1, parent2, pos) From adaf74fc5c6354cf2fb1a9f784e5a37a4fb31caa Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Mon, 12 Apr 2021 08:13:11 -0400 Subject: [PATCH 007/117] Remove spacing and delete old collision comments --- mods/ENTITIES/mcl_mobs/api.lua | 67 ---------------------------------- 1 file changed, 67 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 377244a1c0..a59733e5d9 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -52,8 +52,6 @@ function mobs.is_creative(name) end - - local atan = function(x) if not x or x ~= x then return 0 @@ -213,50 +211,6 @@ local do_attack = function(self, player) --end end - - - ------------------------------------------------------------------------------------------------------------------------------------- - - - - - - - - - - --- collision function borrowed amended from jordan4ibanez open_ai mod ---[[ -local collision = function(self) - - local pos = self.object:get_pos() - local vel = self.object:get_velocity() - local x = 0 - local z = 0 - local width = -self.collisionbox[1] + self.collisionbox[4] + 0.5 - - for _,object in pairs(minetest.get_objects_inside_radius(pos, width)) do - - if object:is_player() - or (object:get_luaentity()._cmi_is_mob == true and object ~= self.object) then - - local pos2 = object:get_pos() - local vec = {x = pos.x - pos2.x, z = pos.z - pos2.z} - local force = (width + 0.5) - vector.distance( - {x = pos.x, y = 0, z = pos.z}, - {x = pos2.x, y = 0, z = pos2.z}) - - x = x + (vec.x * force) - z = z + (vec.z * force) - end - end - - return({x,z}) -end -]]-- - local collision = function(self) pos = self.object:get_pos() --do collision detection from the base of the mob @@ -351,27 +305,6 @@ end - - - - - - - - - ------------------------------------------------------------------------------------------------------------------------------------- - - - - - - - - - - - -- move mob in facing direction local set_velocity = function(self, v) local c_x, c_y = 0, 0 From 6fff719322ee250fc7c074d2362edbf0c4090406 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Mon, 12 Apr 2021 08:47:07 -0400 Subject: [PATCH 008/117] Localize minetest library --- mods/ENTITIES/mcl_mobs/api.lua | 315 ++++++++++++++++++--------------- 1 file changed, 171 insertions(+), 144 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index a59733e5d9..3b2ecfac21 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -4,6 +4,33 @@ -- lua locals +--localize minetest functions +local minetest_settings = minetest.settings +local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius +local minetest_get_modpath = minetest.get_modpath +local minetest_registered_nodes = minetest.registered_nodes +local minetest_get_node = minetest.get_node +local minetest_get_item_group = minetest.get_item_group +local minetest_registered_entities = minetest.registered_entities +local minetest_line_of_sight = minetest.line_of_sight +local minetest_after = minetest.after +local minetest_sound_play = minetest.sound_play +local minetest_add_particlespawner = minetest.add_particlespawner +local minetest_registered_items = minetest.registered_items +local minetest_set_node = minetest.set_node +local minetest_add_item = minetest.add_item +local minetest_get_craft_result = minetest.get_craft_result +local minetest_find_path = minetest.find_path +local minetest_is_protected = minetest.is_protected +local minetest_is_creative_enabled = minetest.is_creative_enabled +local minetest_find_node_near = minetest.find_node_near +local minetest_find_nodes_in_area_under_air = minetest.find_nodes_in_area_under_air +local minetest_raycast = minetest.raycast +local minetest_get_us_time = minetest.get_us_time +local minetest_add_entity = minetest.add_entity +local minetest_get_natural_light = minetest.get_natural_light +local minetest_get_node_or_nil = minetest.get_node_or_nil + -- localize math functions local math_pi = math.pi local math_sin = math.sin @@ -16,21 +43,21 @@ local math_random = math.random local math_floor = math.floor mobs = {} - +-- mob constants local MAX_MOB_NAME_LENGTH = 30 -local BREED_TIME = 30 -local BREED_TIME_AGAIN = 300 -local CHILD_GROW_TIME = 60*20 -local DEATH_DELAY = 0.5 -local DEFAULT_FALL_SPEED = -10 -local FLOP_HEIGHT = 5.0 -local FLOP_HOR_SPEED = 1.5 +local BREED_TIME = 30 +local BREED_TIME_AGAIN = 300 +local CHILD_GROW_TIME = 60*20 +local DEATH_DELAY = 0.5 +local DEFAULT_FALL_SPEED = -10 +local FLOP_HEIGHT = 5.0 +local FLOP_HOR_SPEED = 1.5 -local MOB_CAP = {} +local MOB_CAP = {} MOB_CAP.hostile = 70 MOB_CAP.passive = 10 MOB_CAP.ambient = 15 -MOB_CAP.water = 15 +MOB_CAP.water = 15 -- Localize local S = minetest.get_translator("mcl_mobs") @@ -62,22 +89,22 @@ end -- Load settings -local damage_enabled = minetest.settings:get_bool("enable_damage") -local disable_blood = minetest.settings:get_bool("mobs_disable_blood") -local mobs_drop_items = minetest.settings:get_bool("mobs_drop_items") ~= false -local mobs_griefing = minetest.settings:get_bool("mobs_griefing") ~= false -local spawn_protected = minetest.settings:get_bool("mobs_spawn_protected") ~= false +local damage_enabled = minetest_settings:get_bool("enable_damage") +local disable_blood = minetest_settings:get_bool("mobs_disable_blood") +local mobs_drop_items = minetest_settings:get_bool("mobs_drop_items") ~= false +local mobs_griefing = minetest_settings:get_bool("mobs_griefing") ~= false +local spawn_protected = minetest_settings:get_bool("mobs_spawn_protected") ~= false local remove_far = true -local difficulty = tonumber(minetest.settings:get("mob_difficulty")) or 1.0 +local difficulty = tonumber(minetest_settings:get("mob_difficulty")) or 1.0 local show_health = false -local max_per_block = tonumber(minetest.settings:get("max_objects_per_block") or 64) -local mobs_spawn_chance = tonumber(minetest.settings:get("mobs_spawn_chance") or 2.5) +local max_per_block = tonumber(minetest_settings:get("max_objects_per_block") or 64) +local mobs_spawn_chance = tonumber(minetest_settings:get("mobs_spawn_chance") or 2.5) -- Shows helpful debug info above each mob -local mobs_debug = minetest.settings:get_bool("mobs_debug", false) +local mobs_debug = minetest_settings:get_bool("mobs_debug", false) -- Peaceful mode message so players will know there are no monsters -if minetest.settings:get_bool("only_peaceful_mobs", false) then +if minetest_settings:get_bool("only_peaceful_mobs", false) then minetest.register_on_joinplayer(function(player) minetest.chat_send_player(player:get_player_name(), S("Peaceful mode active! No monsters will spawn.")) @@ -95,13 +122,13 @@ local node_snowblock = "mcl_core:snowblock" local node_snow = "mcl_core:snow" mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" -local mod_weather = minetest.get_modpath("mcl_weather") ~= nil -local mod_explosions = minetest.get_modpath("mcl_explosions") ~= nil -local mod_mobspawners = minetest.get_modpath("mcl_mobspawners") ~= nil -local mod_hunger = minetest.get_modpath("mcl_hunger") ~= nil -local mod_worlds = minetest.get_modpath("mcl_worlds") ~= nil -local mod_armor = minetest.get_modpath("mcl_armor") ~= nil -local mod_experience = minetest.get_modpath("mcl_experience") ~= nil +local mod_weather = minetest_get_modpath("mcl_weather") ~= nil +local mod_explosions = minetest_get_modpath("mcl_explosions") ~= nil +local mod_mobspawners = minetest_get_modpath("mcl_mobspawners") ~= nil +local mod_hunger = minetest_get_modpath("mcl_hunger") ~= nil +local mod_worlds = minetest_get_modpath("mcl_worlds") ~= nil +local mod_armor = minetest_get_modpath("mcl_armor") ~= nil +local mod_experience = minetest_get_modpath("mcl_experience") ~= nil ----For Water Flowing: local enable_physics = function(object, luaentity, ignore_check) @@ -161,7 +188,7 @@ local mob_sound = function(self, soundname, is_opinion, fixed_pitch) -- randomize the pitch a bit pitch = pitch + math_random(-10, 10) * 0.005 end - minetest.sound_play(sound, { + minetest_sound_play(sound, { object = self.object, gain = 1.0, max_hear_distance = self.sounds.distance, @@ -229,7 +256,7 @@ local collision = function(self) collision_count = 0 - for _,object in ipairs(minetest.get_objects_inside_radius(pos, radius*1.25)) do + for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do if object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) and --don't collide with rider, rider don't collide with thing (not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and @@ -469,16 +496,16 @@ end local is_node_dangerous = function(self, nodename) local nn = nodename if self.lava_damage > 0 then - if minetest.get_item_group(nn, "lava") ~= 0 then + if minetest_get_item_group(nn, "lava") ~= 0 then return true end end if self.fire_damage > 0 then - if minetest.get_item_group(nn, "fire") ~= 0 then + if minetest_get_item_group(nn, "fire") ~= 0 then return true end end - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].damage_per_second and minetest.registered_nodes[nn].damage_per_second > 0 then + if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].damage_per_second and minetest_registered_nodes[nn].damage_per_second > 0 then return true end return false @@ -489,15 +516,15 @@ end local is_node_waterhazard = function(self, nodename) local nn = nodename if self.water_damage > 0 then - if minetest.get_item_group(nn, "water") ~= 0 then + if minetest_get_item_group(nn, "water") ~= 0 then return true end end - if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].drowning and minetest.registered_nodes[nn].drowning > 0 then + if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].drowning and minetest_registered_nodes[nn].drowning > 0 then if self.breath_max ~= -1 then -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous - if not self.breathes_in_water and minetest.get_item_group(nn, "water") ~= 0 then + if not self.breathes_in_water and minetest_get_item_group(nn, "water") ~= 0 then return true end end @@ -511,7 +538,7 @@ local line_of_sight = function(self, pos1, pos2, stepsize) stepsize = stepsize or 1 - local s, pos = minetest.line_of_sight(pos1, pos2, stepsize) + local s, pos = minetest_line_of_sight(pos1, pos2, stepsize) -- normal walking and flying mobs can see you through air if s == true then @@ -521,13 +548,13 @@ local line_of_sight = function(self, pos1, pos2, stepsize) -- New pos1 to be analyzed local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} - local r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + local r, pos = minetest_line_of_sight(npos1, pos2, stepsize) -- Checks the return if r == true then return true end -- Nodename found - local nn = minetest.get_node(pos).name + local nn = minetest_get_node(pos).name -- Target Distance (td) to travel local td = vector.distance(pos1, pos2) @@ -537,8 +564,8 @@ local line_of_sight = function(self, pos1, pos2, stepsize) -- It continues to advance in the line of sight in search of a real -- obstruction which counts as 'normal' nodebox. - while minetest.registered_nodes[nn] - and minetest.registered_nodes[nn].walkable == false do + while minetest_registered_nodes[nn] + and minetest_registered_nodes[nn].walkable == false do -- Check if you can still move forward if td < ad + stepsize then @@ -563,12 +590,12 @@ local line_of_sight = function(self, pos1, pos2, stepsize) ad = ad + stepsize -- scan again - r, pos = minetest.line_of_sight(npos1, pos2, stepsize) + r, pos = minetest_line_of_sight(npos1, pos2, stepsize) if r == true then return true end -- New Nodename found - nn = minetest.get_node(pos).name + nn = minetest_get_node(pos).name end @@ -580,7 +607,7 @@ end local flight_check = function(self) local nod = self.standing_in - local def = minetest.registered_nodes[nod] + local def = minetest_registered_nodes[nod] if not def then return false end -- nil check @@ -597,7 +624,7 @@ local flight_check = function(self) if nod == checknode then return true elseif checknode == "__airlike" and def.walkable == false and - (def.liquidtype == "none" or minetest.get_item_group(nod, "fake_liquid") == 1) then + (def.liquidtype == "none" or minetest_get_item_group(nod, "fake_liquid") == 1) then return true end end @@ -623,7 +650,7 @@ local effect = function(pos, amount, texture, min_size, max_size, radius, gravit ym = -radius end - minetest.add_particlespawner({ + minetest_add_particlespawner({ amount = amount, time = 0.25, minpos = pos, @@ -682,7 +709,7 @@ mobs.death_effect = function(pos, yaw, collisionbox, rotate) max = vector.multiply(max, 0.5) end - minetest.add_particlespawner({ + minetest_add_particlespawner({ amount = 50, time = 0.001, minpos = vector.add(pos, min), @@ -698,7 +725,7 @@ mobs.death_effect = function(pos, yaw, collisionbox, rotate) texture = "mcl_particles_mob_death.png^[colorize:#000000:255", }) - minetest.sound_play("mcl_mobs_mob_poof", { + minetest_sound_play("mcl_mobs_mob_poof", { pos = pos, gain = 1.0, max_hear_distance = 8, @@ -780,7 +807,7 @@ local item_drop = function(self, cooked, looting_level) -- cook items when true if cooked then - local output = minetest.get_craft_result({ + local output = minetest_get_craft_result({ method = "cooking", width = 1, items = {item}}) if output and output.item and not output.item:is_empty() then @@ -790,7 +817,7 @@ local item_drop = function(self, cooked, looting_level) -- add item if it exists for x = 1, num do - obj = minetest.add_item(pos, ItemStack(item .. " " .. 1)) + obj = minetest_add_item(pos, ItemStack(item .. " " .. 1)) end if obj and obj:get_luaentity() then @@ -836,7 +863,7 @@ local check_for_death = function(self, cause, cmi_cause) -- play damage sound if health was reduced and make mob flash red. if damaged then add_texture_mod(self, "^[colorize:red:130") - minetest.after(.2, function(self) + minetest_after(.2, function(self) if self and self.object then remove_texture_mod(self, "^[colorize:red:130") end @@ -879,7 +906,7 @@ local check_for_death = function(self, cause, cmi_cause) local looting = mcl_enchanting.get_enchantment(wielditem, "looting") item_drop(self, cooked, looting) - if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest.get_us_time() - self.xp_timestamp <= 5000000) then + if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest_get_us_time() - self.xp_timestamp <= 5000000) then mcl_experience.throw_experience(self.object:get_pos(), math_random(self.xp_min, self.xp_max)) end end @@ -972,7 +999,7 @@ local check_for_death = function(self, cause, cmi_cause) if length <= 0 then kill(self) else - minetest.after(length, kill, self) + minetest_after(length, kill, self) end return true @@ -1016,18 +1043,18 @@ local is_at_cliff_or_danger = function(self) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor - local free_fall, blocker = minetest.line_of_sight( + local free_fall, blocker = minetest_line_of_sight( {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) if free_fall then return true else - local bnode = minetest.get_node(blocker) + local bnode = minetest_get_node(blocker) local danger = is_node_dangerous(self, bnode.name) if danger then return true else - local def = minetest.registered_nodes[bnode.name] + local def = minetest_registered_nodes[bnode.name] if def and def.walkable then return false end @@ -1051,13 +1078,13 @@ local is_at_water_danger = function(self) local pos = self.object:get_pos() local ypos = pos.y + self.collisionbox[2] -- just above floor - local free_fall, blocker = minetest.line_of_sight( + local free_fall, blocker = minetest_line_of_sight( {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) if free_fall then return true else - local bnode = minetest.get_node(blocker) + local bnode = minetest_get_node(blocker) local waterdanger = is_node_waterhazard(self, bnode.name) if waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) then @@ -1065,7 +1092,7 @@ local is_at_water_danger = function(self) elseif waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) == false then return true else - local def = minetest.registered_nodes[bnode.name] + local def = minetest_registered_nodes[bnode.name] if def and def.walkable then return false end @@ -1081,13 +1108,13 @@ local node_ok = function(pos, fallback) fallback = fallback or mobs.fallback_node - local node = minetest.get_node_or_nil(pos) + local node = minetest_get_node_or_nil(pos) - if node and minetest.registered_nodes[node.name] then + if node and minetest_registered_nodes[node.name] then return node end - return minetest.registered_nodes[fallback] + return minetest_registered_nodes[fallback] end @@ -1135,7 +1162,7 @@ local do_env_damage = function(self) -- Use get_node_light for Minetest version 5.3 where get_natural_light -- does not exist yet. - local get_light = minetest.get_natural_light or minetest.get_node_light + local get_light = minetest_get_natural_light or minetest_get_node_light local sunlight = get_light(pos, self.time_of_day) -- bright light harms mob @@ -1174,7 +1201,7 @@ local do_env_damage = function(self) self.object:set_velocity({x = 0, y = 0, z = 0}) end - local nodef = minetest.registered_nodes[self.standing_in] + local nodef = minetest_registered_nodes[self.standing_in] -- rain if self.rain_damage > 0 and mod_weather then @@ -1256,7 +1283,7 @@ local do_env_damage = function(self) if self.breath_max ~= -1 then local drowning = false if self.breathes_in_water then - if minetest.get_item_group(self.standing_in, "water") == 0 then + if minetest_get_item_group(self.standing_in, "water") == 0 then drowning = true end elseif nodef.drowning > 0 then @@ -1348,7 +1375,7 @@ local do_jump = function(self) local nod = node_ok(pos) - if minetest.registered_nodes[nod.name].walkable == false then + if minetest_registered_nodes[nod.name].walkable == false then return false end @@ -1372,7 +1399,7 @@ local do_jump = function(self) }, "air") -- we don't attempt to jump if there's a stack of blocks blocking - if minetest.registered_nodes[nodTop.name].walkable == true then + if minetest_registered_nodes[nodTop.name].walkable == true then return false end @@ -1382,11 +1409,11 @@ local do_jump = function(self) end if self.walk_chance == 0 - or minetest.registered_items[nod.name].walkable then + or minetest_registered_items[nod.name].walkable then - if minetest.get_item_group(nod.name, "fence") == 0 - and minetest.get_item_group(nod.name, "fence_gate") == 0 - and minetest.get_item_group(nod.name, "wall") == 0 then + if minetest_get_item_group(nod.name, "fence") == 0 + and minetest_get_item_group(nod.name, "fence_gate") == 0 + and minetest_get_item_group(nod.name, "wall") == 0 then local v = self.object:get_velocity() @@ -1397,7 +1424,7 @@ local do_jump = function(self) self.object:set_velocity(v) -- when in air move forward - minetest.after(0.3, function(self, v) + minetest_after(0.3, function(self, v) if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then return end @@ -1444,7 +1471,7 @@ local entity_physics = function(pos, radius) radius = radius * 2 - local objs = minetest.get_objects_inside_radius(pos, radius) + local objs = minetest_get_objects_inside_radius(pos, radius) local obj_pos, dist for n = 1, #objs do @@ -1555,7 +1582,7 @@ local breed = function(self) effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) - local objs = minetest.get_objects_inside_radius(pos, 3) + local objs = minetest_get_objects_inside_radius(pos, 3) local num = 0 local ent = nil @@ -1599,7 +1626,7 @@ local breed = function(self) ent.hornytimer = BREED_TIME + 1 -- spawn baby - minetest.after(5, function(parent1, parent2, pos) + minetest_after(5, function(parent1, parent2, pos) if not parent1.object:get_luaentity() then return end @@ -1678,7 +1705,7 @@ local replace = function(self, pos) pos.y = pos.y + y_offset - local node = minetest.get_node(pos) + local node = minetest_get_node(pos) if node.name == what then local oldnode = {name = what, param2 = node.param2} @@ -1692,7 +1719,7 @@ local replace = function(self, pos) if on_replace_return ~= false then if mobs_griefing then - minetest.set_node(pos, newnode) + minetest_set_node(pos, newnode) end end @@ -1736,7 +1763,7 @@ local smart_mobs = function(self, s, p, dist, dtime) self.path.lastpos = {x = s.x, y = s.y, z = s.z} local use_pathfind = false - local has_lineofsight = minetest.line_of_sight( + local has_lineofsight = minetest_line_of_sight( {x = s.x, y = (s.y) + .5, z = s.z}, {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) @@ -1753,7 +1780,7 @@ local smart_mobs = function(self, s, p, dist, dtime) los_switcher = true use_pathfind = false - minetest.after(1, function(self) + minetest_after(1, function(self) if not self.object:get_luaentity() then return end @@ -1767,7 +1794,7 @@ local smart_mobs = function(self, s, p, dist, dtime) use_pathfind = true self.path.stuck_timer = 0 - minetest.after(1, function(self) + minetest_after(1, function(self) if not self.object:get_luaentity() then return end @@ -1780,7 +1807,7 @@ local smart_mobs = function(self, s, p, dist, dtime) use_pathfind = true self.path.stuck_timer = 0 - minetest.after(1, function(self) + minetest_after(1, function(self) if not self.object:get_luaentity() then return end @@ -1811,7 +1838,7 @@ local smart_mobs = function(self, s, p, dist, dtime) s.x = math_floor(s.x + 0.5) s.z = math_floor(s.z + 0.5) - local ssight, sground = minetest.line_of_sight(s, { + local ssight, sground = minetest_line_of_sight(s, { x = s.x, y = s.y - 4, z = s.z}, 1) -- determine node above ground @@ -1833,7 +1860,7 @@ local smart_mobs = function(self, s, p, dist, dtime) elseif self.stepheight > 0.5 then jumpheight = 1 end - self.path.way = minetest.find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") + self.path.way = minetest_find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") self.state = "" do_attack(self, self.attack) @@ -1850,13 +1877,13 @@ local smart_mobs = function(self, s, p, dist, dtime) if s.y < p1.y then -- build upwards - if not minetest.is_protected(s, "") then + if not minetest_is_protected(s, "") then - local ndef1 = minetest.registered_nodes[self.standing_in] + local ndef1 = minetest_registered_nodes[self.standing_in] if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then - minetest.set_node(s, {name = mobs.fallback_node}) + minetest_set_node(s, {name = mobs.fallback_node}) end end @@ -1866,10 +1893,10 @@ local smart_mobs = function(self, s, p, dist, dtime) s.y = s.y + sheight -- remove one block above to make room to jump - if not minetest.is_protected(s, "") then + if not minetest_is_protected(s, "") then local node1 = node_ok(s, "air").name - local ndef1 = minetest.registered_nodes[node1] + local ndef1 = minetest_registered_nodes[node1] if node1 ~= "air" and node1 ~= "ignore" @@ -1878,8 +1905,8 @@ local smart_mobs = function(self, s, p, dist, dtime) and not ndef1.groups.unbreakable and not ndef1.groups.liquid then - minetest.set_node(s, {name = "air"}) - minetest.add_item(s, ItemStack(node1)) + minetest_set_node(s, {name = "air"}) + minetest_add_item(s, ItemStack(node1)) end end @@ -1896,10 +1923,10 @@ local smart_mobs = function(self, s, p, dist, dtime) z = s.z + math_sin(yaw1) } - if not minetest.is_protected(p1, "") then + if not minetest_is_protected(p1, "") then local node1 = node_ok(p1, "air").name - local ndef1 = minetest.registered_nodes[node1] + local ndef1 = minetest_registered_nodes[node1] if node1 ~= "air" and node1 ~= "ignore" @@ -1908,13 +1935,13 @@ local smart_mobs = function(self, s, p, dist, dtime) and not ndef1.groups.unbreakable and not ndef1.groups.liquid then - minetest.add_item(p1, ItemStack(node1)) - minetest.set_node(p1, {name = "air"}) + minetest_add_item(p1, ItemStack(node1)) + minetest_set_node(p1, {name = "air"}) end p1.y = p1.y + 1 node1 = node_ok(p1, "air").name - ndef1 = minetest.registered_nodes[node1] + ndef1 = minetest_registered_nodes[node1] if node1 ~= "air" and node1 ~= "ignore" @@ -1923,8 +1950,8 @@ local smart_mobs = function(self, s, p, dist, dtime) and not ndef1.groups.unbreakable and not ndef1.groups.liquid then - minetest.add_item(p1, ItemStack(node1)) - minetest.set_node(p1, {name = "air"}) + minetest_add_item(p1, ItemStack(node1)) + minetest_set_node(p1, {name = "air"}) end end @@ -1973,7 +2000,7 @@ local monster_attack = function(self) if self.type ~= "monster" or not damage_enabled - or minetest.is_creative_enabled("") + or minetest_is_creative_enabled("") or self.passive or self.state == "attack" or day_docile(self) then @@ -1985,7 +2012,7 @@ local monster_attack = function(self) local player, obj, min_player local type, name = "", "" local min_dist = self.view_range + 1 - local objs = minetest.get_objects_inside_radius(s, self.view_range) + local objs = minetest_get_objects_inside_radius(s, self.view_range) for n = 1, #objs do @@ -2051,7 +2078,7 @@ local npc_attack = function(self) local p, sp, obj, min_player local s = self.object:get_pos() local min_dist = self.view_range + 1 - local objs = minetest.get_objects_inside_radius(s, self.view_range) + local objs = minetest_get_objects_inside_radius(s, self.view_range) for n = 1, #objs do @@ -2114,7 +2141,7 @@ local runaway_from = function(self) local player, obj, min_player local type, name = "", "" local min_dist = self.view_range + 1 - local objs = minetest.get_objects_inside_radius(s, self.view_range) + local objs = minetest_get_objects_inside_radius(s, self.view_range) for n = 1, #objs do @@ -2296,7 +2323,7 @@ local follow_flop = function(self) self.state = "flop" self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) - local sdef = minetest.registered_nodes[self.standing_on] + local sdef = minetest_registered_nodes[self.standing_on] -- Flop on ground if sdef and sdef.walkable then mob_sound(self, "flop") @@ -2359,7 +2386,7 @@ local do_states = function(self, dtime) local lp = nil local s = self.object:get_pos() - local objs = minetest.get_objects_inside_radius(s, 3) + local objs = minetest_get_objects_inside_radius(s, 3) for n = 1, #objs do @@ -2415,19 +2442,19 @@ local do_states = function(self, dtime) and self.lava_damage > 0) or self.breath_max ~= -1 then - lp = minetest.find_node_near(s, 1, {"group:water", "group:lava"}) + lp = minetest_find_node_near(s, 1, {"group:water", "group:lava"}) elseif self.water_damage > 0 then - lp = minetest.find_node_near(s, 1, {"group:water"}) + lp = minetest_find_node_near(s, 1, {"group:water"}) elseif self.lava_damage > 0 then - lp = minetest.find_node_near(s, 1, {"group:lava"}) + lp = minetest_find_node_near(s, 1, {"group:lava"}) elseif self.fire_damage > 0 then - lp = minetest.find_node_near(s, 1, {"group:fire"}) + lp = minetest_find_node_near(s, 1, {"group:fire"}) end @@ -2441,7 +2468,7 @@ local do_states = function(self, dtime) -- If mob in or on dangerous block, look for land if is_in_danger then -- Better way to find shore - copied from upstream - lp = minetest.find_nodes_in_area_under_air( + lp = minetest_find_nodes_in_area_under_air( {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, {x = s.x + 5, y = s.y + 1, z = s.z + 5}, {"group:solid"}) @@ -2637,10 +2664,10 @@ local do_states = function(self, dtime) local pos = self.object:get_pos() if mod_explosions then - if mobs_griefing and not minetest.is_protected(pos, "") then + if mobs_griefing and not minetest_is_protected(pos, "") then mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object) else - minetest.sound_play(self.sounds.explode, { + minetest_sound_play(self.sounds.explode, { pos = pos, gain = 1.0, max_hear_distance = self.sounds.distance or 32 @@ -2860,7 +2887,7 @@ local do_states = function(self, dtime) if self.shoot_interval and self.timer > self.shoot_interval - and not minetest.raycast(p, self.attack:get_pos(), false, false):next() + and not minetest_raycast(p, self.attack:get_pos(), false, false):next() and math_random(1, 100) <= 60 then self.timer = 0 @@ -2870,16 +2897,16 @@ local do_states = function(self, dtime) mob_sound(self, "shoot_attack") -- Shoot arrow - if minetest.registered_entities[self.arrow] then + if minetest_registered_entities[self.arrow] then local arrow, ent local v = 1 if not self.shoot_arrow then self.firing = true - minetest.after(1, function() + minetest_after(1, function() self.firing = false end) - arrow = minetest.add_entity(p, self.arrow) + arrow = minetest_add_entity(p, self.arrow) ent = arrow:get_luaentity() if ent.velocity then v = ent.velocity @@ -2946,7 +2973,7 @@ local falling = function(self, pos) self.object:set_acceleration({x = 0, y = 0, z = 0}) end - if minetest.registered_nodes[node_ok(pos).name].groups.lava then + if minetest_registered_nodes[node_ok(pos).name].groups.lava then if self.floats_on_lava == 1 then @@ -2959,7 +2986,7 @@ local falling = function(self, pos) end -- in water then float up - if minetest.registered_nodes[node_ok(pos).name].groups.water then + if minetest_registered_nodes[node_ok(pos).name].groups.water then if self.floats == 1 then @@ -2979,7 +3006,7 @@ local falling = function(self, pos) if d > 5 then - local add = minetest.get_item_group(self.standing_on, "fall_damage_add_percent") + local add = minetest_get_item_group(self.standing_on, "fall_damage_add_percent") local damage = d - 5 if add ~= 0 then damage = damage + damage * (add/100) @@ -3032,12 +3059,12 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) if is_player then -- is mob protected? - if self.protected and minetest.is_protected(self.object:get_pos(), hitter:get_player_name()) then + if self.protected and minetest_is_protected(self.object:get_pos(), hitter:get_player_name()) then return end -- set/update 'drop xp' timestamp if hitted by player - self.xp_timestamp = minetest.get_us_time() + self.xp_timestamp = minetest_get_us_time() end @@ -3115,11 +3142,11 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) -- add weapon wear manually -- Required because we have custom health handling ("health" property) - if minetest.is_creative_enabled("") ~= true + if minetest_is_creative_enabled("") ~= true and tool_capabilities then if tool_capabilities.punch_attack_uses then -- Without this delay, the wear does not work. Quite hacky ... - minetest.after(0, function(name) + minetest_after(0, function(name) local player = minetest.get_player_by_name(name) if not player then return end local weapon = hitter:get_wielded_item(player) @@ -3143,12 +3170,12 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) local s = math_random(0, #weapon:get_definition().sounds) - minetest.sound_play(weapon:get_definition().sounds[s], { + minetest_sound_play(weapon:get_definition().sounds[s], { object = self.object, --hitter, max_hear_distance = 8 }, true) else - minetest.sound_play("default_punch", { + minetest_sound_play("default_punch", { object = self.object, max_hear_distance = 5 }, true) @@ -3251,7 +3278,7 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) end -- alert others to the attack - local objs = minetest.get_objects_inside_radius(hitter:get_pos(), self.view_range) + local objs = minetest_get_objects_inside_radius(hitter:get_pos(), self.view_range) local obj = nil for n = 1, #objs do @@ -3343,7 +3370,7 @@ local mob_activate = function(self, staticdata, def, dtime) -- remove monsters in peaceful mode if self.type == "monster" - and minetest.settings:get_bool("only_peaceful_mobs", false) then + and minetest_settings:get_bool("only_peaceful_mobs", false) then mcl_burning.extinguish(self.object) self.object:remove() @@ -3680,10 +3707,10 @@ local mob_step = function(self, dtime) -- Add water flowing for mobs from mcl_item_entity local p, node, nn, def p = self.object:get_pos() - node = minetest.get_node_or_nil(p) + node = minetest_get_node_or_nil(p) if node then nn = node.name - def = minetest.registered_nodes[nn] + def = minetest_registered_nodes[nn] end -- Move item around on flowing liquids @@ -3990,7 +4017,7 @@ minetest.register_entity(name, { }) -if minetest.get_modpath("doc_identifier") ~= nil then +if minetest_get_modpath("doc_identifier") ~= nil then doc.sub.identifier.register_object(name, "basics", "mobs") end @@ -4054,7 +4081,7 @@ function mobs:register_arrow(name, def) local node = node_ok(pos).name - if minetest.registered_nodes[node].walkable then + if minetest_registered_nodes[node].walkable then self.hit_node(self, pos, node) @@ -4064,7 +4091,7 @@ function mobs:register_arrow(name, def) self.lastpos = (self.lastpos or pos) - minetest.add_item(self.lastpos, self.object:get_luaentity().name) + minetest_add_item(self.lastpos, self.object:get_luaentity().name) end self.object:remove(); @@ -4075,7 +4102,7 @@ function mobs:register_arrow(name, def) if self.hit_player or self.hit_mob or self.hit_object then - for _,player in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + for _,player in pairs(minetest_get_objects_inside_radius(pos, 1.5)) do if self.hit_player and player:is_player() then @@ -4117,7 +4144,7 @@ end -- no damage to nodes explosion function mobs:safe_boom(self, pos, strength) - minetest.sound_play(self.sounds and self.sounds.explode or "tnt_explode", { + minetest_sound_play(self.sounds and self.sounds.explode or "tnt_explode", { pos = pos, gain = 1.0, max_hear_distance = self.sounds and self.sounds.distance or 32 @@ -4132,7 +4159,7 @@ end function mobs:boom(self, pos, strength, fire) self.object:remove() if mod_explosions then - if mobs_griefing and not minetest.is_protected(pos, "") then + if mobs_griefing and not minetest_is_protected(pos, "") then mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) else mobs:safe_boom(self, pos, strength) @@ -4179,20 +4206,20 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative) local pos = pointed_thing.above -- am I clicking on something with existing on_rightclick function? - local under = minetest.get_node(pointed_thing.under) - local def = minetest.registered_nodes[under.name] + local under = minetest_get_node(pointed_thing.under) + local def = minetest_registered_nodes[under.name] if def and def.on_rightclick then return def.on_rightclick(pointed_thing.under, under, placer, itemstack) end if pos and within_limits(pos, 0) - and not minetest.is_protected(pos, placer:get_player_name()) then + and not minetest_is_protected(pos, placer:get_player_name()) then local name = placer:get_player_name() local privs = minetest.get_player_privs(name) if mod_mobspawners and under.name == "mcl_mobspawners:spawner" then - if minetest.is_protected(pointed_thing.under, name) then + if minetest_is_protected(pointed_thing.under, name) then minetest.record_protection_violation(pointed_thing.under, name) return itemstack end @@ -4207,19 +4234,19 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative) return itemstack end - if not minetest.registered_entities[mob] then + if not minetest_registered_entities[mob] then return itemstack end - if minetest.settings:get_bool("only_peaceful_mobs", false) - and minetest.registered_entities[mob].type == "monster" then + if minetest_settings:get_bool("only_peaceful_mobs", false) + and minetest_registered_entities[mob].type == "monster" then minetest.chat_send_player(name, S("Only peaceful mobs allowed!")) return itemstack end pos.y = pos.y - 0.5 - local mob = minetest.add_entity(pos, mob) + local mob = minetest_add_entity(pos, mob) minetest.log("action", "Mob spawned: "..name.." at "..minetest.pos_to_string(pos)) local ent = mob:get_luaentity() @@ -4343,7 +4370,7 @@ end -- Spawn a child function mobs:spawn_child(pos, mob_type) - local child = minetest.add_entity(pos, mob_type) + local child = minetest_add_entity(pos, mob_type) if not child then return end @@ -4401,8 +4428,8 @@ function mobs:alias_mob(old_name, new_name) on_step = function(self) - if minetest.registered_entities[new_name] then - minetest.add_entity(self.object:get_pos(), new_name) + if minetest_registered_entities[new_name] then + minetest_add_entity(self.object:get_pos(), new_name) end self.object:remove() @@ -4418,7 +4445,7 @@ minetest.register_globalstep(function(dtime) if timer < 1 then return end for _, player in pairs(minetest.get_connected_players()) do local pos = player:get_pos() - for _, obj in pairs(minetest.get_objects_inside_radius(pos, 47)) do + for _, obj in pairs(minetest_get_objects_inside_radius(pos, 47)) do local lua = obj:get_luaentity() if lua and lua._cmi_is_mob then lua.lifetimer = math.max(20, lua.lifetimer) From 3fc0184182f70be0c2fd9b3be1c5d78fa7f00503 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 07:39:57 -0400 Subject: [PATCH 009/117] Disable entire mob ai to work on vanilla walking --- mods/ENTITIES/mcl_mobs/api.lua | 217 +++++++++++++++++---------------- 1 file changed, 115 insertions(+), 102 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 3b2ecfac21..1b234dae28 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -42,6 +42,9 @@ local math_atan = math.atan local math_random = math.random local math_floor = math.floor +-- localize vector functions +local vector_new = vector.new + mobs = {} -- mob constants local MAX_MOB_NAME_LENGTH = 30 @@ -3538,43 +3541,48 @@ local mob_step = function(self, dtime) return false end + if self.state == "die" then + print("need custom die stop moving thing") + return + end + -- can mob be pushed, if so calculate direction -- do this first to prevent issues - -- you can push mobs when they're in the dead state if self.pushable then collision(self) end - if not self.fire_resistant then - mcl_burning.tick(self.object, dtime) - end - if use_cmi then - cmi.notify_step(self.object, dtime) - end + + + --if not self.fire_resistant then + -- mcl_burning.tick(self.object, dtime) + --end + + --if use_cmi then + --cmi.notify_step(self.object, dtime) + --end local pos = self.object:get_pos() local yaw = 0 - if mobs_debug then - update_tag(self) - end + --if mobs_debug then + --update_tag(self) + --end - if self.state == "die" then - return - end - if self.jump_sound_cooloff > 0 then - self.jump_sound_cooloff = self.jump_sound_cooloff - dtime - end - if self.opinion_sound_cooloff > 0 then - self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime - end + --if self.jump_sound_cooloff > 0 then + -- self.jump_sound_cooloff = self.jump_sound_cooloff - dtime + --end - if falling(self, pos) then + --if self.opinion_sound_cooloff > 0 then + -- self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime + --end + + --if falling(self, pos) then -- Return if mob died after falling - return - end + -- return + --end -- smooth rotation by ThomasMonroe314 @@ -3621,24 +3629,24 @@ local mob_step = function(self, dtime) -- end rotation -- run custom function (defined in mob lua file) - if self.do_custom then + --if self.do_custom then -- when false skip going any further - if self.do_custom(self, dtime) == false then - return - end - end + --if self.do_custom(self, dtime) == false then + -- return + --end + --end -- knockback timer - if self.pause_timer > 0 then + --if self.pause_timer > 0 then - self.pause_timer = self.pause_timer - dtime + -- self.pause_timer = self.pause_timer - dtime - return - end + -- return + --end -- attack timer - self.timer = self.timer + dtime + --self.timer = self.timer + dtime --[[ if self.state ~= "attack" then @@ -3653,99 +3661,102 @@ local mob_step = function(self, dtime) ]]-- -- never go over 100 - if self.timer > 100 then - self.timer = 1 - end + --if self.timer > 100 then + -- self.timer = 1 + --end -- mob plays random sound at times - if math_random(1, 70) == 1 then - mob_sound(self, "random", true) - end + --if math_random(1, 70) == 1 then + -- mob_sound(self, "random", true) + --end -- environmental damage timer (every 1 second) - self.env_damage_timer = self.env_damage_timer + dtime - - if (self.state == "attack" and self.env_damage_timer > 1) - or self.state ~= "attack" then - - self.env_damage_timer = 0 - - -- check for environmental damage (water, fire, lava etc.) - if do_env_damage(self) then - return - end + --self.env_damage_timer = self.env_damage_timer + dtime + --if (self.state == "attack" and self.env_damage_timer > 1) + --or self.state ~= "attack" then + -- + -- self.env_damage_timer = 0 + -- + -- -- check for environmental damage (water, fire, lava etc.) + -- if do_env_damage(self) then + -- return + -- end + -- -- node replace check (cow eats grass etc.) - replace(self, pos) - end + -- replace(self, pos) + --end - monster_attack(self) + --monster_attack(self) - npc_attack(self) + --npc_attack(self) - breed(self) + --breed(self) - if do_states(self, dtime) then - return - end + --if do_states(self, dtime) then + -- return + --end - do_jump(self) + --do_jump(self) - runaway_from(self) + --runaway_from(self) - if is_at_water_danger(self) and self.state ~= "attack" then - if math_random(1, 10) <= 6 then - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - yaw = yaw + math_random(-0.5, 0.5) - yaw = set_yaw(self, yaw, 8) - end - end + + --if is_at_water_danger(self) and self.state ~= "attack" then + -- if math_random(1, 10) <= 6 then + -- set_velocity(self, 0) + -- self.state = "stand" + -- set_animation(self, "stand") + -- yaw = yaw + math_random(-0.5, 0.5) + -- yaw = set_yaw(self, yaw, 8) + -- end + --end -- Add water flowing for mobs from mcl_item_entity - local p, node, nn, def - p = self.object:get_pos() - node = minetest_get_node_or_nil(p) - if node then - nn = node.name - def = minetest_registered_nodes[nn] - end + --[[ + local p, node, nn, def + p = self.object:get_pos() + node = minetest_get_node_or_nil(p) + if node then + nn = node.name + def = minetest_registered_nodes[nn] + end - -- Move item around on flowing liquids - if def and def.liquidtype == "flowing" then - - --[[ Get flowing direction (function call from flowlib), if there's a liquid. - NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. - Luckily, this is exactly what we need if we only care about water, which has this flowing distance. ]] - local vec = flowlib.quick_flow(p, node) - -- Just to make sure we don't manipulate the speed for no reason - if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then - -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" - local f = 1.39 - -- Set new item moving speed into the direciton of the liquid - local newv = vector.multiply(vec, f) - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) + -- Move item around on flowing liquids + if def and def.liquidtype == "flowing" then + + -- Get flowing direction (function call from flowlib), if there's a liquid. + NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. + Luckily, this is exactly what we need if we only care about water, which has this flowing distance. + local vec = flowlib.quick_flow(p, node) + -- Just to make sure we don't manipulate the speed for no reason + if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then + -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" + local f = 1.39 + -- Set new item moving speed into the direciton of the liquid + local newv = vector.multiply(vec, f) + self.object:set_acceleration({x = 0, y = 0, z = 0}) + self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) - self.physical_state = true - self._flowing = true - self.object:set_properties({ - physical = true - }) - return - end - elseif self._flowing == true then - -- Disable flowing physics if not on/in flowing liquid - self._flowing = false - enable_physics(self.object, self, true) + self.physical_state = true + self._flowing = true + self.object:set_properties({ + physical = true + }) return end + elseif self._flowing == true then + -- Disable flowing physics if not on/in flowing liquid + self._flowing = false + enable_physics(self.object, self, true) + return + end --Mob following code. follow_flop(self) + if is_at_cliff_or_danger(self) then set_velocity(self, 0) self.state = "stand" @@ -3774,6 +3785,7 @@ local mob_step = function(self, dtime) end end end + ]]-- end @@ -4005,7 +4017,8 @@ minetest.register_entity(name, { --default built in engine collision detection self.object:set_properties({ collide_with_objects = false, - }) + }) + self.object:set_acceleration(vector_new(0,-9.81, 0)) return mob_activate(self, staticdata, def, dtime) end, From 02515f0778bbe9cd962acc514b084c9dedf55074 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 08:07:32 -0400 Subject: [PATCH 010/117] Move a large chunk of code to backup_code_api.lua --- mods/ENTITIES/mcl_mobs/api.lua | 1558 +------------------- mods/ENTITIES/mcl_mobs/backup_code_api.lua | 1466 ++++++++++++++++++ 2 files changed, 1530 insertions(+), 1494 deletions(-) create mode 100644 mods/ENTITIES/mcl_mobs/backup_code_api.lua diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 1b234dae28..3619ca3628 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -1,6 +1,6 @@ -- API for Mobs Redo: MineClone 2 Delux 2.0 DRM Free Early Access Super Extreme Edition --- current state of things: "why are these not in the same table as those?", and, "why are these not localized?" +-- current state of things: Why? -- lua locals @@ -62,6 +62,11 @@ MOB_CAP.passive = 10 MOB_CAP.ambient = 15 MOB_CAP.water = 15 + +-- random locals I found +local los_switcher = false +local height_switcher = false + -- Localize local S = minetest.get_translator("mcl_mobs") @@ -133,30 +138,6 @@ local mod_worlds = minetest_get_modpath("mcl_worlds") ~= nil local mod_armor = minetest_get_modpath("mcl_armor") ~= nil local mod_experience = minetest_get_modpath("mcl_experience") ~= nil -----For Water Flowing: -local enable_physics = function(object, luaentity, ignore_check) - if luaentity.physical_state == false or ignore_check == true then - luaentity.physical_state = true - object:set_properties({ - physical = true - }) - object:set_velocity({x=0,y=0,z=0}) - object:set_acceleration({x=0,y=-9.81,z=0}) - end -end - -local disable_physics = function(object, luaentity, ignore_check, reset_movement) - if luaentity.physical_state == true or ignore_check == true then - luaentity.physical_state = false - object:set_properties({ - physical = false - }) - if reset_movement ~= false then - object:set_velocity({x=0,y=0,z=0}) - object:set_acceleration({x=0,y=0,z=0}) - end - end -end -- play sound @@ -424,36 +405,6 @@ function mobs:yaw(self, yaw, delay, dtime) set_yaw(self, yaw, delay, dtime) end -local add_texture_mod = function(self, mod) - local full_mod = "" - local already_added = false - for i=1, #self.texture_mods do - if mod == self.texture_mods[i] then - already_added = true - end - full_mod = full_mod .. self.texture_mods[i] - end - if not already_added then - full_mod = full_mod .. mod - table.insert(self.texture_mods, mod) - end - self.object:set_texture_mod(full_mod) -end -local remove_texture_mod = function(self, mod) - local full_mod = "" - local remove = {} - for i=1, #self.texture_mods do - if self.texture_mods[i] ~= mod then - full_mod = full_mod .. self.texture_mods[i] - else - table.insert(remove, i) - end - end - for i=#remove, 1 do - table.remove(self.texture_mods, remove[i]) - end - self.object:set_texture_mod(full_mod) -end -- set defined animation local set_animation = function(self, anim, fixed_frame) @@ -495,206 +446,6 @@ function mobs:set_animation(self, anim) set_animation(self, anim) end --- Returns true is node can deal damage to self -local is_node_dangerous = function(self, nodename) - local nn = nodename - if self.lava_damage > 0 then - if minetest_get_item_group(nn, "lava") ~= 0 then - return true - end - end - if self.fire_damage > 0 then - if minetest_get_item_group(nn, "fire") ~= 0 then - return true - end - end - if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].damage_per_second and minetest_registered_nodes[nn].damage_per_second > 0 then - return true - end - return false -end - - --- Returns true if node is a water hazard -local is_node_waterhazard = function(self, nodename) - local nn = nodename - if self.water_damage > 0 then - if minetest_get_item_group(nn, "water") ~= 0 then - return true - end - end - if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].drowning and minetest_registered_nodes[nn].drowning > 0 then - if self.breath_max ~= -1 then - -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case - -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous - if not self.breathes_in_water and minetest_get_item_group(nn, "water") ~= 0 then - return true - end - end - end - return false -end - - --- check line of sight (BrunoMine) -local line_of_sight = function(self, pos1, pos2, stepsize) - - stepsize = stepsize or 1 - - local s, pos = minetest_line_of_sight(pos1, pos2, stepsize) - - -- normal walking and flying mobs can see you through air - if s == true then - return true - end - - -- New pos1 to be analyzed - local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} - - local r, pos = minetest_line_of_sight(npos1, pos2, stepsize) - - -- Checks the return - if r == true then return true end - - -- Nodename found - local nn = minetest_get_node(pos).name - - -- Target Distance (td) to travel - local td = vector.distance(pos1, pos2) - - -- Actual Distance (ad) traveled - local ad = 0 - - -- It continues to advance in the line of sight in search of a real - -- obstruction which counts as 'normal' nodebox. - while minetest_registered_nodes[nn] - and minetest_registered_nodes[nn].walkable == false do - - -- Check if you can still move forward - if td < ad + stepsize then - return true -- Reached the target - end - - -- Moves the analyzed pos - local d = vector.distance(pos1, pos2) - - npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x - npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y - npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z - - -- NaN checks - if d == 0 - or npos1.x ~= npos1.x - or npos1.y ~= npos1.y - or npos1.z ~= npos1.z then - return false - end - - ad = ad + stepsize - - -- scan again - r, pos = minetest_line_of_sight(npos1, pos2, stepsize) - - if r == true then return true end - - -- New Nodename found - nn = minetest_get_node(pos).name - - end - - return false -end - - --- are we flying in what we are suppose to? (taikedz) -local flight_check = function(self) - - local nod = self.standing_in - local def = minetest_registered_nodes[nod] - - if not def then return false end -- nil check - - local fly_in - if type(self.fly_in) == "string" then - fly_in = { self.fly_in } - elseif type(self.fly_in) == "table" then - fly_in = self.fly_in - else - return false - end - - for _,checknode in pairs(fly_in) do - if nod == checknode then - return true - elseif checknode == "__airlike" and def.walkable == false and - (def.liquidtype == "none" or minetest_get_item_group(nod, "fake_liquid") == 1) then - return true - end - end - - return false -end - - --- custom particle effects -local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down) - - radius = radius or 2 - min_size = min_size or 0.5 - max_size = max_size or 1 - gravity = gravity or -10 - glow = glow or 0 - go_down = go_down or false - - local ym - if go_down then - ym = 0 - else - ym = -radius - end - - minetest_add_particlespawner({ - amount = amount, - time = 0.25, - minpos = pos, - maxpos = pos, - minvel = {x = -radius, y = ym, z = -radius}, - maxvel = {x = radius, y = radius, z = radius}, - minacc = {x = 0, y = gravity, z = 0}, - maxacc = {x = 0, y = gravity, z = 0}, - minexptime = 0.1, - maxexptime = 1, - minsize = min_size, - maxsize = max_size, - texture = texture, - glow = glow, - }) -end - -local damage_effect = function(self, damage) - -- damage particles - if (not disable_blood) and damage > 0 then - - local amount_large = math_floor(damage / 2) - local amount_small = damage % 2 - - local pos = self.object:get_pos() - - pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5 - - local texture = "mobs_blood.png" - -- full heart damage (one particle for each 2 HP damage) - if amount_large > 0 then - effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true) - end - -- half heart damage (one additional particle if damage is an odd number) - if amount_small > 0 then - -- TODO: Use "half heart" - effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true) - end - end -end - mobs.death_effect = function(pos, yaw, collisionbox, rotate) local min, max if collisionbox then @@ -735,279 +486,6 @@ mobs.death_effect = function(pos, yaw, collisionbox, rotate) }, true) end -local update_tag = function(self) - local tag - if mobs_debug then - tag = "nametag = '"..tostring(self.nametag).."'\n".. - "state = '"..tostring(self.state).."'\n".. - "order = '"..tostring(self.order).."'\n".. - "attack = "..tostring(self.attack).."\n".. - "health = "..tostring(self.health).."\n".. - "breath = "..tostring(self.breath).."\n".. - "gotten = "..tostring(self.gotten).."\n".. - "tamed = "..tostring(self.tamed).."\n".. - "horny = "..tostring(self.horny).."\n".. - "hornytimer = "..tostring(self.hornytimer).."\n".. - "runaway_timer = "..tostring(self.runaway_timer).."\n".. - "following = "..tostring(self.following) - else - tag = self.nametag - end - self.object:set_properties({ - nametag = tag, - }) - - update_roll(self) -end - --- drop items -local item_drop = function(self, cooked, looting_level) - - -- no drops if disabled by setting - if not mobs_drop_items then return end - - looting_level = looting_level or 0 - - -- no drops for child mobs (except monster) - if (self.child and self.type ~= "monster") then - return - end - - local obj, item, num - local pos = self.object:get_pos() - - self.drops = self.drops or {} -- nil check - - for n = 1, #self.drops do - local dropdef = self.drops[n] - local chance = 1 / dropdef.chance - local looting_type = dropdef.looting - - if looting_level > 0 then - local chance_function = dropdef.looting_chance_function - if chance_function then - chance = chance_function(looting_level) - elseif looting_type == "rare" then - chance = chance + (dropdef.looting_factor or 0.01) * looting_level - end - end - - local num = 0 - local do_common_looting = (looting_level > 0 and looting_type == "common") - if math_random() < chance then - num = math_random(dropdef.min or 1, dropdef.max or 1) - elseif not dropdef.looting_ignore_chance then - do_common_looting = false - end - - if do_common_looting then - num = num + math_floor(math_random(0, looting_level) + 0.5) - end - - if num > 0 then - item = dropdef.name - - -- cook items when true - if cooked then - - local output = minetest_get_craft_result({ - method = "cooking", width = 1, items = {item}}) - - if output and output.item and not output.item:is_empty() then - item = output.item:get_name() - end - end - - -- add item if it exists - for x = 1, num do - obj = minetest_add_item(pos, ItemStack(item .. " " .. 1)) - end - - if obj and obj:get_luaentity() then - - obj:set_velocity({ - x = math_random(-10, 10) / 9, - y = 6, - z = math_random(-10, 10) / 9, - }) - elseif obj then - obj:remove() -- item does not exist - end - end - end - - self.drops = {} -end - - --- check if mob is dead or only hurt -local check_for_death = function(self, cause, cmi_cause) - - if self.state == "die" then - return true - end - - -- has health actually changed? - if self.health == self.old_health and self.health > 0 then - return false - end - - local damaged = self.health < self.old_health - self.old_health = self.health - - -- still got some health? - if self.health > 0 then - - -- make sure health isn't higher than max - if self.health > self.hp_max then - self.health = self.hp_max - end - - -- play damage sound if health was reduced and make mob flash red. - if damaged then - add_texture_mod(self, "^[colorize:red:130") - minetest_after(.2, function(self) - if self and self.object then - remove_texture_mod(self, "^[colorize:red:130") - end - end, self) - mob_sound(self, "damage") - end - - -- backup nametag so we can show health stats - if not self.nametag2 then - self.nametag2 = self.nametag or "" - end - - if show_health - and (cmi_cause and cmi_cause.type == "punch") then - - self.htimer = 2 - self.nametag = "♥ " .. self.health .. " / " .. self.hp_max - - update_tag(self) - end - - return false - end - - mob_sound(self, "death") - - local function death_handle(self) - -- dropped cooked item if mob died in fire or lava - if cause == "lava" or cause == "fire" then - item_drop(self, true, 0) - else - local wielditem = ItemStack() - if cause == "hit" then - local puncher = cmi_cause.puncher - if puncher then - wielditem = puncher:get_wielded_item() - end - end - local cooked = mcl_burning.is_burning(self.object) or mcl_enchanting.has_enchantment(wielditem, "fire_aspect") - local looting = mcl_enchanting.get_enchantment(wielditem, "looting") - item_drop(self, cooked, looting) - - if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest_get_us_time() - self.xp_timestamp <= 5000000) then - mcl_experience.throw_experience(self.object:get_pos(), math_random(self.xp_min, self.xp_max)) - end - end - end - - -- execute custom death function - if self.on_die then - - local pos = self.object:get_pos() - local on_die_exit = self.on_die(self, pos, cmi_cause) - if on_die_exit ~= true then - death_handle(self) - end - - if use_cmi then - cmi.notify_die(self.object, cmi_cause) - end - - if on_die_exit == true then - self.state = "die" - mcl_burning.extinguish(self.object) - self.object:remove() - return true - end - end - - local collisionbox - if self.collisionbox then - collisionbox = table.copy(self.collisionbox) - end - - self.state = "die" - self.attack = nil - self.v_start = false - self.fall_speed = DEFAULT_FALL_SPEED - self.timer = 0 - self.blinktimer = 0 - remove_texture_mod(self, "^[colorize:#FF000040") - remove_texture_mod(self, "^[brighten") - self.passive = true - - self.object:set_properties({ - pointable = false, - collide_with_objects = false, - }) - - set_velocity(self, 0) - local acc = self.object:get_acceleration() - acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0 - self.object:set_acceleration(acc) - - local length - -- default death function and die animation (if defined) - if self.instant_death then - length = 0 - elseif self.animation - and self.animation.die_start - and self.animation.die_end then - - local frames = self.animation.die_end - self.animation.die_start - local speed = self.animation.die_speed or 15 - length = max(frames / speed, 0) + DEATH_DELAY - set_animation(self, "die") - else - local rot = self.object:get_rotation() - rot.z = math_pi/2 - self.object:set_rotation(rot) - length = 1 + DEATH_DELAY - set_animation(self, "stand", true) - end - - - -- Remove body after a few seconds and drop stuff - local kill = function(self) - if not self.object:get_luaentity() then - return - end - if use_cmi then - cmi.notify_die(self.object, cmi_cause) - end - - death_handle(self) - local dpos = self.object:get_pos() - local cbox = self.collisionbox - local yaw = self.object:get_rotation().y - mcl_burning.extinguish(self.object) - self.object:remove() - mobs.death_effect(dpos, yaw, cbox, not self.instant_death) - end - if length <= 0 then - kill(self) - else - minetest_after(length, kill, self) - end - - return true -end - -- check if within physical map limits (-30911 to 30927) local within_limits, wmin, wmax = nil, -30913, 30928 @@ -1746,636 +1224,7 @@ local day_docile = function(self) end -local los_switcher = false -local height_switcher = false --- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 -local smart_mobs = function(self, s, p, dist, dtime) - - local s1 = self.path.lastpos - - local target_pos = self.attack:get_pos() - - -- is it becoming stuck? - if math_abs(s1.x - s.x) + math_abs(s1.z - s.z) < .5 then - self.path.stuck_timer = self.path.stuck_timer + dtime - else - self.path.stuck_timer = 0 - end - - self.path.lastpos = {x = s.x, y = s.y, z = s.z} - - local use_pathfind = false - local has_lineofsight = minetest_line_of_sight( - {x = s.x, y = (s.y) + .5, z = s.z}, - {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) - - -- im stuck, search for path - if not has_lineofsight then - - if los_switcher == true then - use_pathfind = true - los_switcher = false - end -- cannot see target! - else - if los_switcher == false then - - los_switcher = true - use_pathfind = false - - minetest_after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end -- can see target! - end - - if (self.path.stuck_timer > stuck_timeout and not self.path.following) then - - use_pathfind = true - self.path.stuck_timer = 0 - - minetest_after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end - - if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then - - use_pathfind = true - self.path.stuck_timer = 0 - - minetest_after(1, function(self) - if not self.object:get_luaentity() then - return - end - if has_lineofsight then self.path.following = false end - end, self) - end - - if math_abs(vector.subtract(s,target_pos).y) > self.stepheight then - - if height_switcher then - use_pathfind = true - height_switcher = false - end - else - if not height_switcher then - use_pathfind = false - height_switcher = true - end - end - - if use_pathfind then - -- lets try find a path, first take care of positions - -- since pathfinder is very sensitive - local sheight = self.collisionbox[5] - self.collisionbox[2] - - -- round position to center of node to avoid stuck in walls - -- also adjust height for player models! - s.x = math_floor(s.x + 0.5) - s.z = math_floor(s.z + 0.5) - - local ssight, sground = minetest_line_of_sight(s, { - x = s.x, y = s.y - 4, z = s.z}, 1) - - -- determine node above ground - if not ssight then - s.y = sground.y + 1 - end - - local p1 = self.attack:get_pos() - - p1.x = math_floor(p1.x + 0.5) - p1.y = math_floor(p1.y + 0.5) - p1.z = math_floor(p1.z + 0.5) - - local dropheight = 12 - if self.fear_height ~= 0 then dropheight = self.fear_height end - local jumpheight = 0 - if self.jump and self.jump_height >= 4 then - jumpheight = math.min(math.ceil(self.jump_height / 4), 4) - elseif self.stepheight > 0.5 then - jumpheight = 1 - end - self.path.way = minetest_find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") - - self.state = "" - do_attack(self, self.attack) - - -- no path found, try something else - if not self.path.way then - - self.path.following = false - - -- lets make way by digging/building if not accessible - if self.pathfinding == 2 and mobs_griefing then - - -- is player higher than mob? - if s.y < p1.y then - - -- build upwards - if not minetest_is_protected(s, "") then - - local ndef1 = minetest_registered_nodes[self.standing_in] - - if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then - - minetest_set_node(s, {name = mobs.fallback_node}) - end - end - - local sheight = math.ceil(self.collisionbox[5]) + 1 - - -- assume mob is 2 blocks high so it digs above its head - s.y = s.y + sheight - - -- remove one block above to make room to jump - if not minetest_is_protected(s, "") then - - local node1 = node_ok(s, "air").name - local ndef1 = minetest_registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest_set_node(s, {name = "air"}) - minetest_add_item(s, ItemStack(node1)) - - end - end - - s.y = s.y - sheight - self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) - - else -- dig 2 blocks to make door toward player direction - - local yaw1 = self.object:get_yaw() + math_pi / 2 - local p1 = { - x = s.x + math_cos(yaw1), - y = s.y, - z = s.z + math_sin(yaw1) - } - - if not minetest_is_protected(p1, "") then - - local node1 = node_ok(p1, "air").name - local ndef1 = minetest_registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest_add_item(p1, ItemStack(node1)) - minetest_set_node(p1, {name = "air"}) - end - - p1.y = p1.y + 1 - node1 = node_ok(p1, "air").name - ndef1 = minetest_registered_nodes[node1] - - if node1 ~= "air" - and node1 ~= "ignore" - and ndef1 - and not ndef1.groups.level - and not ndef1.groups.unbreakable - and not ndef1.groups.liquid then - - minetest_add_item(p1, ItemStack(node1)) - minetest_set_node(p1, {name = "air"}) - end - - end - end - end - - -- will try again in 2 seconds - self.path.stuck_timer = stuck_timeout - 2 - elseif s.y < p1.y and (not self.fly) then - do_jump(self) --add jump to pathfinding - self.path.following = true - -- Yay, I found path! - -- TODO: Implement war_cry sound without being annoying - --mob_sound(self, "war_cry", true) - else - set_velocity(self, self.walk_velocity) - - -- follow path now that it has it - self.path.following = true - end - end -end - - --- specific attacks -local specific_attack = function(list, what) - - -- no list so attack default (player, animals etc.) - if list == nil then - return true - end - - -- found entity on list to attack? - for no = 1, #list do - - if list[no] == what then - return true - end - end - - return false -end - --- monster find someone to attack -local monster_attack = function(self) - - if self.type ~= "monster" - or not damage_enabled - or minetest_is_creative_enabled("") - or self.passive - or self.state == "attack" - or day_docile(self) then - return - end - - local s = self.object:get_pos() - local p, sp, dist - local player, obj, min_player - local type, name = "", "" - local min_dist = self.view_range + 1 - local objs = minetest_get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - if objs[n]:is_player() then - - if mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then - type = "" - else - player = objs[n] - type = "player" - name = "player" - end - else - obj = objs[n]:get_luaentity() - - if obj then - player = obj.object - type = obj.type - name = obj.name or "" - end - end - - -- find specific mob to attack, failing that attack player/npc/animal - if specific_attack(self.specific_attack, name) - and (type == "player" or type == "npc" - or (type == "animal" and self.attack_animals == true)) then - - p = player:get_pos() - sp = s - - dist = vector.distance(p, s) - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - - -- choose closest player to attack - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = player - end - end - end - - -- attack player - if min_player then - do_attack(self, min_player) - end -end - - --- npc, find closest monster to attack -local npc_attack = function(self) - - if self.type ~= "npc" - or not self.attacks_monsters - or self.state == "attack" then - return - end - - local p, sp, obj, min_player - local s = self.object:get_pos() - local min_dist = self.view_range + 1 - local objs = minetest_get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - obj = objs[n]:get_luaentity() - - if obj and obj.type == "monster" then - - p = obj.object:get_pos() - sp = s - - local dist = vector.distance(p, s) - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = obj.object - end - end - end - - if min_player then - do_attack(self, min_player) - end -end - - --- specific runaway -local specific_runaway = function(list, what) - - -- no list so do not run - if list == nil then - return false - end - - -- found entity on list to attack? - for no = 1, #list do - - if list[no] == what then - return true - end - end - - return false -end - - --- find someone to runaway from -local runaway_from = function(self) - - if not self.runaway_from and self.state ~= "flop" then - return - end - - local s = self.object:get_pos() - local p, sp, dist - local player, obj, min_player - local type, name = "", "" - local min_dist = self.view_range + 1 - local objs = minetest_get_objects_inside_radius(s, self.view_range) - - for n = 1, #objs do - - if objs[n]:is_player() then - - if mobs.invis[ objs[n]:get_player_name() ] - or self.owner == objs[n]:get_player_name() - or (not object_in_range(self, objs[n])) then - type = "" - else - player = objs[n] - type = "player" - name = "player" - end - else - obj = objs[n]:get_luaentity() - - if obj then - player = obj.object - type = obj.type - name = obj.name or "" - end - end - - -- find specific mob to runaway from - if name ~= "" and name ~= self.name - and specific_runaway(self.runaway_from, name) then - - p = player:get_pos() - sp = s - - -- aim higher to make looking up hills more realistic - p.y = p.y + 1 - sp.y = sp.y + 1 - - dist = vector.distance(p, s) - - - -- choose closest player/mpb to runaway from - if dist < min_dist - and line_of_sight(self, sp, p, 2) == true then - min_dist = dist - min_player = player - end - end - end - - if min_player then - - local lp = player:get_pos() - local vec = { - x = lp.x - s.x, - y = lp.y - s.y, - z = lp.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate - - if lp.x > s.x then - yaw = yaw + math_pi - end - - yaw = set_yaw(self, yaw, 4) - self.state = "runaway" - self.runaway_timer = 3 - self.following = nil - end -end - - --- follow player if owner or holding item, if fish outta water then flop -local follow_flop = function(self) - - -- find player to follow - if (self.follow ~= "" - or self.order == "follow") - and not self.following - and self.state ~= "attack" - and self.order ~= "sit" - and self.state ~= "runaway" then - - local s = self.object:get_pos() - local players = minetest.get_connected_players() - - for n = 1, #players do - - if (object_in_range(self, players[n])) - and not mobs.invis[ players[n]:get_player_name() ] then - - self.following = players[n] - - break - end - end - end - - if self.type == "npc" - and self.order == "follow" - and self.state ~= "attack" - and self.order ~= "sit" - and self.owner ~= "" then - - -- npc stop following player if not owner - if self.following - and self.owner - and self.owner ~= self.following:get_player_name() then - self.following = nil - end - else - -- stop following player if not holding specific item, - -- mob is horny, fleeing or attacking - if self.following - and self.following:is_player() - and (follow_holding(self, self.following) == false or - self.horny or self.state == "runaway") then - self.following = nil - end - - end - - -- follow that thing - if self.following then - - local s = self.object:get_pos() - local p - - if self.following:is_player() then - - p = self.following:get_pos() - - elseif self.following.object then - - p = self.following.object:get_pos() - end - - if p then - - local dist = vector.distance(p, s) - - -- dont follow if out of range - if (not object_in_range(self, self.following)) then - self.following = nil - else - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + math_pi end - - set_yaw(self, yaw, 2.35) - - -- anyone but standing npc's can move along - if dist > 3 - and self.order ~= "stand" then - - set_velocity(self, self.follow_velocity) - - if self.walk_chance ~= 0 then - set_animation(self, "run") - end - else - set_velocity(self, 0) - set_animation(self, "stand") - end - - return - end - end - end - - -- swimmers flop when out of their element, and swim again when back in - if self.fly then - local s = self.object:get_pos() - if not flight_check(self, s) then - - self.state = "flop" - self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) - - local sdef = minetest_registered_nodes[self.standing_on] - -- Flop on ground - if sdef and sdef.walkable then - mob_sound(self, "flop") - self.object:set_velocity({ - x = math_random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), - y = FLOP_HEIGHT, - z = math_random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), - }) - end - - set_animation(self, "stand", true) - - return - elseif self.state == "flop" then - self.state = "stand" - self.object:set_acceleration({x = 0, y = 0, z = 0}) - set_velocity(self, 0) - end - end -end - - --- dogshoot attack switch and counter function -local dogswitch = function(self, dtime) - - -- switch mode not activated - if not self.dogshoot_switch - or not dtime then - return 0 - end - - self.dogshoot_count = self.dogshoot_count + dtime - - if (self.dogshoot_switch == 1 - and self.dogshoot_count > self.dogshoot_count_max) - or (self.dogshoot_switch == 2 - and self.dogshoot_count > self.dogshoot_count2_max) then - - self.dogshoot_count = 0 - - if self.dogshoot_switch == 1 then - self.dogshoot_switch = 2 - else - self.dogshoot_switch = 1 - end - end - - return self.dogshoot_switch -end -- execute current state (stand, walk, run, attacks) -- returns true if mob has died @@ -2936,110 +1785,6 @@ local do_states = function(self, dtime) end end - --- falling and fall damage --- returns true if mob died -local falling = function(self, pos) - - if self.fly and self.state ~= "die" then - return - end - - if mcl_portals ~= nil then - if mcl_portals.nether_portal_cooloff(self.object) then - return false -- mob has teleported through Nether portal - it's 99% not falling - end - end - - -- floating in water (or falling) - local v = self.object:get_velocity() - - if v.y > 0 then - - -- apply gravity when moving up - self.object:set_acceleration({ - x = 0, - y = -10, - z = 0 - }) - - elseif v.y <= 0 and v.y > self.fall_speed then - - -- fall downwards at set speed - self.object:set_acceleration({ - x = 0, - y = self.fall_speed, - z = 0 - }) - else - -- stop accelerating once max fall speed hit - self.object:set_acceleration({x = 0, y = 0, z = 0}) - end - - if minetest_registered_nodes[node_ok(pos).name].groups.lava then - - if self.floats_on_lava == 1 then - - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (max(1, v.y) ^ 2), - z = 0 - }) - end - end - - -- in water then float up - if minetest_registered_nodes[node_ok(pos).name].groups.water then - - if self.floats == 1 then - - self.object:set_acceleration({ - x = 0, - y = -self.fall_speed / (math_max(1, v.y) ^ 2), - z = 0 - }) - end - else - - -- fall damage onto solid ground - if self.fall_damage == 1 - and self.object:get_velocity().y == 0 then - - local d = (self.old_y or 0) - self.object:get_pos().y - - if d > 5 then - - local add = minetest_get_item_group(self.standing_on, "fall_damage_add_percent") - local damage = d - 5 - if add ~= 0 then - damage = damage + damage * (add/100) - end - damage = math_floor(damage) - if damage > 0 then - self.health = self.health - damage - - effect(pos, 5, "mcl_particles_smoke.png", 1, 2, 2, nil) - - if check_for_death(self, "fall", {type = "fall"}) then - return true - end - end - end - - self.old_y = self.object:get_pos().y - end - end -end - -local teleport = function(self, target) - if self.do_teleport then - if self.do_teleport(self, target) == false then - return - end - end -end - - -- deal damage and effects when mob punched local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) @@ -3720,34 +2465,7 @@ local mob_step = function(self, dtime) node = minetest_get_node_or_nil(p) if node then nn = node.name - def = minetest_registered_nodes[nn] - end - - -- Move item around on flowing liquids - if def and def.liquidtype == "flowing" then - - -- Get flowing direction (function call from flowlib), if there's a liquid. - NOTE: According to Qwertymine, flowlib.quickflow is only reliable for liquids with a flowing distance of 7. - Luckily, this is exactly what we need if we only care about water, which has this flowing distance. - local vec = flowlib.quick_flow(p, node) - -- Just to make sure we don't manipulate the speed for no reason - if vec.x ~= 0 or vec.y ~= 0 or vec.z ~= 0 then - -- Minecraft Wiki: Flowing speed is "about 1.39 meters per second" - local f = 1.39 - -- Set new item moving speed into the direciton of the liquid - local newv = vector.multiply(vec, f) - self.object:set_acceleration({x = 0, y = 0, z = 0}) - self.object:set_velocity({x = newv.x, y = -0.22, z = newv.z}) - - self.physical_state = true - self._flowing = true - self.object:set_properties({ - physical = true - }) - return - end - elseif self._flowing == true then - -- Disable flowing physics if not on/in flowing liquid + def = minetest_registered_nodes[nnenable_physicss if not on/in flowing liquid self._flowing = false enable_physics(self.object, self, true) return @@ -3869,6 +2587,63 @@ if collisionbox[5] < 0.79 then collisionbox[5] = 0.79 end + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + minetest.register_entity(name, { use_texture_alpha = def.use_texture_alpha, @@ -4154,35 +2929,6 @@ function mobs:register_arrow(name, def) }) end - --- no damage to nodes explosion -function mobs:safe_boom(self, pos, strength) - minetest_sound_play(self.sounds and self.sounds.explode or "tnt_explode", { - pos = pos, - gain = 1.0, - max_hear_distance = self.sounds and self.sounds.distance or 32 - }, true) - local radius = strength - entity_physics(pos, radius) - effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0) -end - - --- make explosion with protection and tnt mod check -function mobs:boom(self, pos, strength, fire) - self.object:remove() - if mod_explosions then - if mobs_griefing and not minetest_is_protected(pos, "") then - mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) - else - mobs:safe_boom(self, pos, strength) - end - else - mobs:safe_boom(self, pos, strength) - end -end - - -- Register spawn eggs -- Note: This also introduces the “spawn_egg” group: @@ -4293,179 +3039,3 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative) end --- No-op in MCL2 (capturing mobs is not possible). --- Provided for compability with Mobs Redo -function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) - return false -end - - --- No-op in MCL2 (protecting mobs is not possible). -function mobs:protect(self, clicker) - return false -end - - --- feeding, taming and breeding (thanks blert2112) -function mobs:feed_tame(self, clicker, feed_count, breed, tame) - if not self.follow then - return false - end - - -- can eat/tame with item in hand - if follow_holding(self, clicker) then - - -- if not in creative then take item - if not mobs.is_creative(clicker:get_player_name()) then - - local item = clicker:get_wielded_item() - - item:take_item() - - clicker:set_wielded_item(item) - end - - mob_sound(self, "eat", nil, true) - - -- increase health - self.health = self.health + 4 - - if self.health >= self.hp_max then - - self.health = self.hp_max - - if self.htimer < 1 then - self.htimer = 5 - end - end - - self.object:set_hp(self.health) - - update_tag(self) - - -- make children grow quicker - if self.child == true then - - -- deduct 10% of the time to adulthood - self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1) - - return true - end - - -- feed and tame - self.food = (self.food or 0) + 1 - if self.food >= feed_count then - - self.food = 0 - - if breed and self.hornytimer == 0 then - self.horny = true - end - - if tame then - - self.tamed = true - - if not self.owner or self.owner == "" then - self.owner = clicker:get_player_name() - end - end - - -- make sound when fed so many times - mob_sound(self, "random", true) - end - - return true - end - - return false -end - --- Spawn a child -function mobs:spawn_child(pos, mob_type) - local child = minetest_add_entity(pos, mob_type) - if not child then - return - end - - local ent = child:get_luaentity() - effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5) - - ent.child = true - - local textures - -- using specific child texture (if found) - if ent.child_texture then - textures = ent.child_texture[1] - end - - -- and resize to half height - child:set_properties({ - textures = textures, - visual_size = { - x = ent.base_size.x * .5, - y = ent.base_size.y * .5, - }, - collisionbox = { - ent.base_colbox[1] * .5, - ent.base_colbox[2] * .5, - ent.base_colbox[3] * .5, - ent.base_colbox[4] * .5, - ent.base_colbox[5] * .5, - ent.base_colbox[6] * .5, - }, - selectionbox = { - ent.base_selbox[1] * .5, - ent.base_selbox[2] * .5, - ent.base_selbox[3] * .5, - ent.base_selbox[4] * .5, - ent.base_selbox[5] * .5, - ent.base_selbox[6] * .5, - }, - }) - - return child -end - - --- compatibility function for old entities to new modpack entities -function mobs:alias_mob(old_name, new_name) - - -- spawn egg - minetest.register_alias(old_name, new_name) - - -- entity - minetest.register_entity(":" .. old_name, { - - physical = false, - - on_step = function(self) - - if minetest_registered_entities[new_name] then - minetest_add_entity(self.object:get_pos(), new_name) - end - - self.object:remove() - end - }) - -end - ---[[ -local timer = 0 -minetest.register_globalstep(function(dtime) - timer = timer + dtime - if timer < 1 then return end - for _, player in pairs(minetest.get_connected_players()) do - local pos = player:get_pos() - for _, obj in pairs(minetest_get_objects_inside_radius(pos, 47)) do - local lua = obj:get_luaentity() - if lua and lua._cmi_is_mob then - lua.lifetimer = math.max(20, lua.lifetimer) - lua.despawn_immediately = false - end - end - end - timer = 0 -end) -]]-- \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/backup_code_api.lua new file mode 100644 index 0000000000..ba4b8452af --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/backup_code_api.lua @@ -0,0 +1,1466 @@ +local disable_physics = function(object, luaentity, ignore_check, reset_movement) + if luaentity.physical_state == true or ignore_check == true then + luaentity.physical_state = false + object:set_properties({ + physical = false + }) + if reset_movement ~= false then + object:set_velocity({x=0,y=0,z=0}) + object:set_acceleration({x=0,y=0,z=0}) + end + end +end + +----For Water Flowing: +local enable_physics = function(object, luaentity, ignore_check) + if luaentity.physical_state == false or ignore_check == true then + luaentity.physical_state = true + object:set_properties({ + physical = true + }) + object:set_velocity({x=0,y=0,z=0}) + object:set_acceleration({x=0,y=-9.81,z=0}) + end +end + +--[[ +local timer = 0 +minetest.register_globalstep(function(dtime) + timer = timer + dtime + if timer < 1 then return end + for _, player in pairs(minetest.get_connected_players()) do + local pos = player:get_pos() + for _, obj in pairs(minetest_get_objects_inside_radius(pos, 47)) do + local lua = obj:get_luaentity() + if lua and lua._cmi_is_mob then + lua.lifetimer = math.max(20, lua.lifetimer) + lua.despawn_immediately = false + end + end + end + timer = 0 +end) +]]-- + +-- compatibility function for old entities to new modpack entities +function mobs:alias_mob(old_name, new_name) + + -- spawn egg + minetest.register_alias(old_name, new_name) + + -- entity + minetest.register_entity(":" .. old_name, { + + physical = false, + + on_step = function(self) + + if minetest_registered_entities[new_name] then + minetest_add_entity(self.object:get_pos(), new_name) + end + + self.object:remove() + end + }) +end + + +-- Spawn a child +function mobs:spawn_child(pos, mob_type) + local child = minetest_add_entity(pos, mob_type) + if not child then + return + end + + local ent = child:get_luaentity() + effect(pos, 15, "mcl_particles_smoke.png", 1, 2, 2, 15, 5) + + ent.child = true + + local textures + -- using specific child texture (if found) + if ent.child_texture then + textures = ent.child_texture[1] + end + + -- and resize to half height + child:set_properties({ + textures = textures, + visual_size = { + x = ent.base_size.x * .5, + y = ent.base_size.y * .5, + }, + collisionbox = { + ent.base_colbox[1] * .5, + ent.base_colbox[2] * .5, + ent.base_colbox[3] * .5, + ent.base_colbox[4] * .5, + ent.base_colbox[5] * .5, + ent.base_colbox[6] * .5, + }, + selectionbox = { + ent.base_selbox[1] * .5, + ent.base_selbox[2] * .5, + ent.base_selbox[3] * .5, + ent.base_selbox[4] * .5, + ent.base_selbox[5] * .5, + ent.base_selbox[6] * .5, + }, + }) + + return child +end + + +-- No-op in MCL2 (capturing mobs is not possible). +-- Provided for compability with Mobs Redo +function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) + return false +end + + +-- No-op in MCL2 (protecting mobs is not possible). +function mobs:protect(self, clicker) + return false +end + + +-- feeding, taming and breeding (thanks blert2112) +function mobs:feed_tame(self, clicker, feed_count, breed, tame) + if not self.follow then + return false + end + + -- can eat/tame with item in hand + if follow_holding(self, clicker) then + + -- if not in creative then take item + if not mobs.is_creative(clicker:get_player_name()) then + + local item = clicker:get_wielded_item() + + item:take_item() + + clicker:set_wielded_item(item) + end + + mob_sound(self, "eat", nil, true) + + -- increase health + self.health = self.health + 4 + + if self.health >= self.hp_max then + + self.health = self.hp_max + + if self.htimer < 1 then + self.htimer = 5 + end + end + + self.object:set_hp(self.health) + + update_tag(self) + + -- make children grow quicker + if self.child == true then + + -- deduct 10% of the time to adulthood + self.hornytimer = self.hornytimer + ((CHILD_GROW_TIME - self.hornytimer) * 0.1) + + return true + end + + -- feed and tame + self.food = (self.food or 0) + 1 + if self.food >= feed_count then + + self.food = 0 + + if breed and self.hornytimer == 0 then + self.horny = true + end + + if tame then + + self.tamed = true + + if not self.owner or self.owner == "" then + self.owner = clicker:get_player_name() + end + end + + -- make sound when fed so many times + mob_sound(self, "random", true) + end + + return true + end + + return false +end + +-- no damage to nodes explosion +function mobs:safe_boom(self, pos, strength) + minetest_sound_play(self.sounds and self.sounds.explode or "tnt_explode", { + pos = pos, + gain = 1.0, + max_hear_distance = self.sounds and self.sounds.distance or 32 + }, true) + local radius = strength + entity_physics(pos, radius) + effect(pos, 32, "mcl_particles_smoke.png", radius * 3, radius * 5, radius, 1, 0) +end + + +-- make explosion with protection and tnt mod check +function mobs:boom(self, pos, strength, fire) + self.object:remove() + if mod_explosions then + if mobs_griefing and not minetest_is_protected(pos, "") then + mcl_explosions.explode(pos, strength, { drop_chance = 1.0, fire = fire }, self.object) + else + mobs:safe_boom(self, pos, strength) + end + else + mobs:safe_boom(self, pos, strength) + end +end + +-- falling and fall damage +-- returns true if mob died +local falling = function(self, pos) + + if self.fly and self.state ~= "die" then + return + end + + if mcl_portals ~= nil then + if mcl_portals.nether_portal_cooloff(self.object) then + return false -- mob has teleported through Nether portal - it's 99% not falling + end + end + + -- floating in water (or falling) + local v = self.object:get_velocity() + + if v.y > 0 then + + -- apply gravity when moving up + self.object:set_acceleration({ + x = 0, + y = -10, + z = 0 + }) + + elseif v.y <= 0 and v.y > self.fall_speed then + + -- fall downwards at set speed + self.object:set_acceleration({ + x = 0, + y = self.fall_speed, + z = 0 + }) + else + -- stop accelerating once max fall speed hit + self.object:set_acceleration({x = 0, y = 0, z = 0}) + end + + if minetest_registered_nodes[node_ok(pos).name].groups.lava then + + if self.floats_on_lava == 1 then + + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (max(1, v.y) ^ 2), + z = 0 + }) + end + end + + -- in water then float up + if minetest_registered_nodes[node_ok(pos).name].groups.water then + + if self.floats == 1 then + + self.object:set_acceleration({ + x = 0, + y = -self.fall_speed / (math_max(1, v.y) ^ 2), + z = 0 + }) + end + else + + -- fall damage onto solid ground + if self.fall_damage == 1 + and self.object:get_velocity().y == 0 then + + local d = (self.old_y or 0) - self.object:get_pos().y + + if d > 5 then + + local add = minetest_get_item_group(self.standing_on, "fall_damage_add_percent") + local damage = d - 5 + if add ~= 0 then + damage = damage + damage * (add/100) + end + damage = math_floor(damage) + if damage > 0 then + self.health = self.health - damage + + effect(pos, 5, "mcl_particles_smoke.png", 1, 2, 2, nil) + + if check_for_death(self, "fall", {type = "fall"}) then + return true + end + end + end + + self.old_y = self.object:get_pos().y + end + end +end + +local teleport = function(self, target) + if self.do_teleport then + if self.do_teleport(self, target) == false then + return + end + end +end + + +-- find someone to runaway from +local runaway_from = function(self) + + if not self.runaway_from and self.state ~= "flop" then + return + end + + local s = self.object:get_pos() + local p, sp, dist + local player, obj, min_player + local type, name = "", "" + local min_dist = self.view_range + 1 + local objs = minetest_get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + if objs[n]:is_player() then + + if mobs.invis[ objs[n]:get_player_name() ] + or self.owner == objs[n]:get_player_name() + or (not object_in_range(self, objs[n])) then + type = "" + else + player = objs[n] + type = "player" + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + type = obj.type + name = obj.name or "" + end + end + + -- find specific mob to runaway from + if name ~= "" and name ~= self.name + and specific_runaway(self.runaway_from, name) then + + p = player:get_pos() + sp = s + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + dist = vector.distance(p, s) + + + -- choose closest player/mpb to runaway from + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + + if min_player then + + local lp = player:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + math_pi + end + + yaw = set_yaw(self, yaw, 4) + self.state = "runaway" + self.runaway_timer = 3 + self.following = nil + end +end + + +-- specific runaway +local specific_runaway = function(list, what) + + -- no list so do not run + if list == nil then + return false + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + + +-- follow player if owner or holding item, if fish outta water then flop +local follow_flop = function(self) + + -- find player to follow + if (self.follow ~= "" + or self.order == "follow") + and not self.following + and self.state ~= "attack" + and self.order ~= "sit" + and self.state ~= "runaway" then + + local s = self.object:get_pos() + local players = minetest.get_connected_players() + + for n = 1, #players do + + if (object_in_range(self, players[n])) + and not mobs.invis[ players[n]:get_player_name() ] then + + self.following = players[n] + + break + end + end + end + + if self.type == "npc" + and self.order == "follow" + and self.state ~= "attack" + and self.order ~= "sit" + and self.owner ~= "" then + + -- npc stop following player if not owner + if self.following + and self.owner + and self.owner ~= self.following:get_player_name() then + self.following = nil + end + else + -- stop following player if not holding specific item, + -- mob is horny, fleeing or attacking + if self.following + and self.following:is_player() + and (follow_holding(self, self.following) == false or + self.horny or self.state == "runaway") then + self.following = nil + end + + end + + -- follow that thing + if self.following then + + local s = self.object:get_pos() + local p + + if self.following:is_player() then + + p = self.following:get_pos() + + elseif self.following.object then + + p = self.following.object:get_pos() + end + + if p then + + local dist = vector.distance(p, s) + + -- dont follow if out of range + if (not object_in_range(self, self.following)) then + self.following = nil + else + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + math_pi end + + set_yaw(self, yaw, 2.35) + + -- anyone but standing npc's can move along + if dist > 3 + and self.order ~= "stand" then + + set_velocity(self, self.follow_velocity) + + if self.walk_chance ~= 0 then + set_animation(self, "run") + end + else + set_velocity(self, 0) + set_animation(self, "stand") + end + + return + end + end + end + + -- swimmers flop when out of their element, and swim again when back in + if self.fly then + local s = self.object:get_pos() + if not flight_check(self, s) then + + self.state = "flop" + self.object:set_acceleration({x = 0, y = DEFAULT_FALL_SPEED, z = 0}) + + local sdef = minetest_registered_nodes[self.standing_on] + -- Flop on ground + if sdef and sdef.walkable then + mob_sound(self, "flop") + self.object:set_velocity({ + x = math_random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + y = FLOP_HEIGHT, + z = math_random(-FLOP_HOR_SPEED, FLOP_HOR_SPEED), + }) + end + + set_animation(self, "stand", true) + + return + elseif self.state == "flop" then + self.state = "stand" + self.object:set_acceleration({x = 0, y = 0, z = 0}) + set_velocity(self, 0) + end + end +end + + +-- npc, find closest monster to attack +local npc_attack = function(self) + + if self.type ~= "npc" + or not self.attacks_monsters + or self.state == "attack" then + return + end + + local p, sp, obj, min_player + local s = self.object:get_pos() + local min_dist = self.view_range + 1 + local objs = minetest_get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj and obj.type == "monster" then + + p = obj.object:get_pos() + sp = s + + local dist = vector.distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = obj.object + end + end + end + + if min_player then + do_attack(self, min_player) + end +end + + +-- monster find someone to attack +local monster_attack = function(self) + + if self.type ~= "monster" + or not damage_enabled + or minetest_is_creative_enabled("") + or self.passive + or self.state == "attack" + or day_docile(self) then + return + end + + local s = self.object:get_pos() + local p, sp, dist + local player, obj, min_player + local type, name = "", "" + local min_dist = self.view_range + 1 + local objs = minetest_get_objects_inside_radius(s, self.view_range) + + for n = 1, #objs do + + if objs[n]:is_player() then + + if mobs.invis[ objs[n]:get_player_name() ] or (not object_in_range(self, objs[n])) then + type = "" + else + player = objs[n] + type = "player" + name = "player" + end + else + obj = objs[n]:get_luaentity() + + if obj then + player = obj.object + type = obj.type + name = obj.name or "" + end + end + + -- find specific mob to attack, failing that attack player/npc/animal + if specific_attack(self.specific_attack, name) + and (type == "player" or type == "npc" + or (type == "animal" and self.attack_animals == true)) then + + p = player:get_pos() + sp = s + + dist = vector.distance(p, s) + + -- aim higher to make looking up hills more realistic + p.y = p.y + 1 + sp.y = sp.y + 1 + + + -- choose closest player to attack + if dist < min_dist + and line_of_sight(self, sp, p, 2) == true then + min_dist = dist + min_player = player + end + end + end + + -- attack player + if min_player then + do_attack(self, min_player) + end +end + + +-- specific attacks +local specific_attack = function(list, what) + + -- no list so attack default (player, animals etc.) + if list == nil then + return true + end + + -- found entity on list to attack? + for no = 1, #list do + + if list[no] == what then + return true + end + end + + return false +end + + +-- dogfight attack switch and counter function +local dogswitch = function(self, dtime) + + -- switch mode not activated + if not self.dogshoot_switch + or not dtime then + return 0 + end + + self.dogshoot_count = self.dogshoot_count + dtime + + if (self.dogshoot_switch == 1 + and self.dogshoot_count > self.dogshoot_count_max) + or (self.dogshoot_switch == 2 + and self.dogshoot_count > self.dogshoot_count2_max) then + + self.dogshoot_count = 0 + + if self.dogshoot_switch == 1 then + self.dogshoot_switch = 2 + else + self.dogshoot_switch = 1 + end + end + + return self.dogshoot_switch +end + +-- path finding and smart mob routine by rnd, line_of_sight and other edits by Elkien3 +local smart_mobs = function(self, s, p, dist, dtime) + + local s1 = self.path.lastpos + + local target_pos = self.attack:get_pos() + + -- is it becoming stuck? + if math_abs(s1.x - s.x) + math_abs(s1.z - s.z) < .5 then + self.path.stuck_timer = self.path.stuck_timer + dtime + else + self.path.stuck_timer = 0 + end + + self.path.lastpos = {x = s.x, y = s.y, z = s.z} + + local use_pathfind = false + local has_lineofsight = minetest_line_of_sight( + {x = s.x, y = (s.y) + .5, z = s.z}, + {x = target_pos.x, y = (target_pos.y) + 1.5, z = target_pos.z}, .2) + + -- im stuck, search for path + if not has_lineofsight then + + if los_switcher == true then + use_pathfind = true + los_switcher = false + end -- cannot see target! + else + if los_switcher == false then + + los_switcher = true + use_pathfind = false + + minetest_after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end -- can see target! + end + + if (self.path.stuck_timer > stuck_timeout and not self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest_after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end + + if (self.path.stuck_timer > stuck_path_timeout and self.path.following) then + + use_pathfind = true + self.path.stuck_timer = 0 + + minetest_after(1, function(self) + if not self.object:get_luaentity() then + return + end + if has_lineofsight then self.path.following = false end + end, self) + end + + if math_abs(vector.subtract(s,target_pos).y) > self.stepheight then + + if height_switcher then + use_pathfind = true + height_switcher = false + end + else + if not height_switcher then + use_pathfind = false + height_switcher = true + end + end + + if use_pathfind then + -- lets try find a path, first take care of positions + -- since pathfinder is very sensitive + local sheight = self.collisionbox[5] - self.collisionbox[2] + + -- round position to center of node to avoid stuck in walls + -- also adjust height for player models! + s.x = math_floor(s.x + 0.5) + s.z = math_floor(s.z + 0.5) + + local ssight, sground = minetest_line_of_sight(s, { + x = s.x, y = s.y - 4, z = s.z}, 1) + + -- determine node above ground + if not ssight then + s.y = sground.y + 1 + end + + local p1 = self.attack:get_pos() + + p1.x = math_floor(p1.x + 0.5) + p1.y = math_floor(p1.y + 0.5) + p1.z = math_floor(p1.z + 0.5) + + local dropheight = 12 + if self.fear_height ~= 0 then dropheight = self.fear_height end + local jumpheight = 0 + if self.jump and self.jump_height >= 4 then + jumpheight = math.min(math.ceil(self.jump_height / 4), 4) + elseif self.stepheight > 0.5 then + jumpheight = 1 + end + self.path.way = minetest_find_path(s, p1, 16, jumpheight, dropheight, "A*_noprefetch") + + self.state = "" + do_attack(self, self.attack) + + -- no path found, try something else + if not self.path.way then + + self.path.following = false + + -- lets make way by digging/building if not accessible + if self.pathfinding == 2 and mobs_griefing then + + -- is player higher than mob? + if s.y < p1.y then + + -- build upwards + if not minetest_is_protected(s, "") then + + local ndef1 = minetest_registered_nodes[self.standing_in] + + if ndef1 and (ndef1.buildable_to or ndef1.groups.liquid) then + + minetest_set_node(s, {name = mobs.fallback_node}) + end + end + + local sheight = math.ceil(self.collisionbox[5]) + 1 + + -- assume mob is 2 blocks high so it digs above its head + s.y = s.y + sheight + + -- remove one block above to make room to jump + if not minetest_is_protected(s, "") then + + local node1 = node_ok(s, "air").name + local ndef1 = minetest_registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest_set_node(s, {name = "air"}) + minetest_add_item(s, ItemStack(node1)) + + end + end + + s.y = s.y - sheight + self.object:set_pos({x = s.x, y = s.y + 2, z = s.z}) + + else -- dig 2 blocks to make door toward player direction + + local yaw1 = self.object:get_yaw() + math_pi / 2 + local p1 = { + x = s.x + math_cos(yaw1), + y = s.y, + z = s.z + math_sin(yaw1) + } + + if not minetest_is_protected(p1, "") then + + local node1 = node_ok(p1, "air").name + local ndef1 = minetest_registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest_add_item(p1, ItemStack(node1)) + minetest_set_node(p1, {name = "air"}) + end + + p1.y = p1.y + 1 + node1 = node_ok(p1, "air").name + ndef1 = minetest_registered_nodes[node1] + + if node1 ~= "air" + and node1 ~= "ignore" + and ndef1 + and not ndef1.groups.level + and not ndef1.groups.unbreakable + and not ndef1.groups.liquid then + + minetest_add_item(p1, ItemStack(node1)) + minetest_set_node(p1, {name = "air"}) + end + + end + end + end + + -- will try again in 2 seconds + self.path.stuck_timer = stuck_timeout - 2 + elseif s.y < p1.y and (not self.fly) then + do_jump(self) --add jump to pathfinding + self.path.following = true + -- Yay, I found path! + -- TODO: Implement war_cry sound without being annoying + --mob_sound(self, "war_cry", true) + else + set_velocity(self, self.walk_velocity) + + -- follow path now that it has it + self.path.following = true + end + end +end + +local update_tag = function(self) + local tag + if mobs_debug then + tag = "nametag = '"..tostring(self.nametag).."'\n".. + "state = '"..tostring(self.state).."'\n".. + "order = '"..tostring(self.order).."'\n".. + "attack = "..tostring(self.attack).."\n".. + "health = "..tostring(self.health).."\n".. + "breath = "..tostring(self.breath).."\n".. + "gotten = "..tostring(self.gotten).."\n".. + "tamed = "..tostring(self.tamed).."\n".. + "horny = "..tostring(self.horny).."\n".. + "hornytimer = "..tostring(self.hornytimer).."\n".. + "runaway_timer = "..tostring(self.runaway_timer).."\n".. + "following = "..tostring(self.following) + else + tag = self.nametag + end + self.object:set_properties({ + nametag = tag, + }) + + update_roll(self) +end + +-- drop items +local item_drop = function(self, cooked, looting_level) + + -- no drops if disabled by setting + if not mobs_drop_items then return end + + looting_level = looting_level or 0 + + -- no drops for child mobs (except monster) + if (self.child and self.type ~= "monster") then + return + end + + local obj, item, num + local pos = self.object:get_pos() + + self.drops = self.drops or {} -- nil check + + for n = 1, #self.drops do + local dropdef = self.drops[n] + local chance = 1 / dropdef.chance + local looting_type = dropdef.looting + + if looting_level > 0 then + local chance_function = dropdef.looting_chance_function + if chance_function then + chance = chance_function(looting_level) + elseif looting_type == "rare" then + chance = chance + (dropdef.looting_factor or 0.01) * looting_level + end + end + + local num = 0 + local do_common_looting = (looting_level > 0 and looting_type == "common") + if math_random() < chance then + num = math_random(dropdef.min or 1, dropdef.max or 1) + elseif not dropdef.looting_ignore_chance then + do_common_looting = false + end + + if do_common_looting then + num = num + math_floor(math_random(0, looting_level) + 0.5) + end + + if num > 0 then + item = dropdef.name + + -- cook items when true + if cooked then + + local output = minetest_get_craft_result({ + method = "cooking", width = 1, items = {item}}) + + if output and output.item and not output.item:is_empty() then + item = output.item:get_name() + end + end + + -- add item if it exists + for x = 1, num do + obj = minetest_add_item(pos, ItemStack(item .. " " .. 1)) + end + + if obj and obj:get_luaentity() then + + obj:set_velocity({ + x = math_random(-10, 10) / 9, + y = 6, + z = math_random(-10, 10) / 9, + }) + elseif obj then + obj:remove() -- item does not exist + end + end + end + + self.drops = {} +end + + +-- check if mob is dead or only hurt +local check_for_death = function(self, cause, cmi_cause) + + if self.state == "die" then + return true + end + + -- has health actually changed? + if self.health == self.old_health and self.health > 0 then + return false + end + + local damaged = self.health < self.old_health + self.old_health = self.health + + -- still got some health? + if self.health > 0 then + + -- make sure health isn't higher than max + if self.health > self.hp_max then + self.health = self.hp_max + end + + -- play damage sound if health was reduced and make mob flash red. + if damaged then + add_texture_mod(self, "^[colorize:red:130") + minetest_after(.2, function(self) + if self and self.object then + remove_texture_mod(self, "^[colorize:red:130") + end + end, self) + mob_sound(self, "damage") + end + + -- backup nametag so we can show health stats + if not self.nametag2 then + self.nametag2 = self.nametag or "" + end + + if show_health + and (cmi_cause and cmi_cause.type == "punch") then + + self.htimer = 2 + self.nametag = "♥ " .. self.health .. " / " .. self.hp_max + + update_tag(self) + end + + return false + end + + mob_sound(self, "death") + + local function death_handle(self) + -- dropped cooked item if mob died in fire or lava + if cause == "lava" or cause == "fire" then + item_drop(self, true, 0) + else + local wielditem = ItemStack() + if cause == "hit" then + local puncher = cmi_cause.puncher + if puncher then + wielditem = puncher:get_wielded_item() + end + end + local cooked = mcl_burning.is_burning(self.object) or mcl_enchanting.has_enchantment(wielditem, "fire_aspect") + local looting = mcl_enchanting.get_enchantment(wielditem, "looting") + item_drop(self, cooked, looting) + + if mod_experience and ((not self.child) or self.type ~= "animal") and (minetest_get_us_time() - self.xp_timestamp <= 5000000) then + mcl_experience.throw_experience(self.object:get_pos(), math_random(self.xp_min, self.xp_max)) + end + end + end + + -- execute custom death function + if self.on_die then + + local pos = self.object:get_pos() + local on_die_exit = self.on_die(self, pos, cmi_cause) + if on_die_exit ~= true then + death_handle(self) + end + + if use_cmi then + cmi.notify_die(self.object, cmi_cause) + end + + if on_die_exit == true then + self.state = "die" + mcl_burning.extinguish(self.object) + self.object:remove() + return true + end + end + + local collisionbox + if self.collisionbox then + collisionbox = table.copy(self.collisionbox) + end + + self.state = "die" + self.attack = nil + self.v_start = false + self.fall_speed = DEFAULT_FALL_SPEED + self.timer = 0 + self.blinktimer = 0 + remove_texture_mod(self, "^[colorize:#FF000040") + remove_texture_mod(self, "^[brighten") + self.passive = true + + self.object:set_properties({ + pointable = false, + collide_with_objects = false, + }) + + set_velocity(self, 0) + local acc = self.object:get_acceleration() + acc.x, acc.y, acc.z = 0, DEFAULT_FALL_SPEED, 0 + self.object:set_acceleration(acc) + + local length + -- default death function and die animation (if defined) + if self.instant_death then + length = 0 + elseif self.animation + and self.animation.die_start + and self.animation.die_end then + + local frames = self.animation.die_end - self.animation.die_start + local speed = self.animation.die_speed or 15 + length = max(frames / speed, 0) + DEATH_DELAY + set_animation(self, "die") + else + local rot = self.object:get_rotation() + rot.z = math_pi/2 + self.object:set_rotation(rot) + length = 1 + DEATH_DELAY + set_animation(self, "stand", true) + end + + + -- Remove body after a few seconds and drop stuff + local kill = function(self) + if not self.object:get_luaentity() then + return + end + if use_cmi then + cmi.notify_die(self.object, cmi_cause) + end + + death_handle(self) + local dpos = self.object:get_pos() + local cbox = self.collisionbox + local yaw = self.object:get_rotation().y + mcl_burning.extinguish(self.object) + self.object:remove() + mobs.death_effect(dpos, yaw, cbox, not self.instant_death) + end + if length <= 0 then + kill(self) + else + minetest_after(length, kill, self) + end + + return true +end + +local damage_effect = function(self, damage) + -- damage particles + if (not disable_blood) and damage > 0 then + + local amount_large = math_floor(damage / 2) + local amount_small = damage % 2 + + local pos = self.object:get_pos() + + pos.y = pos.y + (self.collisionbox[5] - self.collisionbox[2]) * .5 + + local texture = "mobs_blood.png" + -- full heart damage (one particle for each 2 HP damage) + if amount_large > 0 then + effect(pos, amount_large, texture, 2, 2, 1.75, 0, nil, true) + end + -- half heart damage (one additional particle if damage is an odd number) + if amount_small > 0 then + -- TODO: Use "half heart" + effect(pos, amount_small, texture, 1, 1, 1.75, 0, nil, true) + end + end +end + + +-- custom particle effects +local effect = function(pos, amount, texture, min_size, max_size, radius, gravity, glow, go_down) + + radius = radius or 2 + min_size = min_size or 0.5 + max_size = max_size or 1 + gravity = gravity or -10 + glow = glow or 0 + go_down = go_down or false + + local ym + if go_down then + ym = 0 + else + ym = -radius + end + + minetest_add_particlespawner({ + amount = amount, + time = 0.25, + minpos = pos, + maxpos = pos, + minvel = {x = -radius, y = ym, z = -radius}, + maxvel = {x = radius, y = radius, z = radius}, + minacc = {x = 0, y = gravity, z = 0}, + maxacc = {x = 0, y = gravity, z = 0}, + minexptime = 0.1, + maxexptime = 1, + minsize = min_size, + maxsize = max_size, + texture = texture, + glow = glow, + }) +end + + +-- are we flying in what we are suppose to? (taikedz) +local flight_check = function(self) + + local nod = self.standing_in + local def = minetest_registered_nodes[nod] + + if not def then return false end -- nil check + + local fly_in + if type(self.fly_in) == "string" then + fly_in = { self.fly_in } + elseif type(self.fly_in) == "table" then + fly_in = self.fly_in + else + return false + end + + for _,checknode in pairs(fly_in) do + if nod == checknode then + return true + elseif checknode == "__airlike" and def.walkable == false and + (def.liquidtype == "none" or minetest_get_item_group(nod, "fake_liquid") == 1) then + return true + end + end + + return false +end + + +-- check line of sight (BrunoMine) +local line_of_sight = function(self, pos1, pos2, stepsize) + + stepsize = stepsize or 1 + + local s, pos = minetest_line_of_sight(pos1, pos2, stepsize) + + -- normal walking and flying mobs can see you through air + if s == true then + return true + end + + -- New pos1 to be analyzed + local npos1 = {x = pos1.x, y = pos1.y, z = pos1.z} + + local r, pos = minetest_line_of_sight(npos1, pos2, stepsize) + + -- Checks the return + if r == true then return true end + + -- Nodename found + local nn = minetest_get_node(pos).name + + -- Target Distance (td) to travel + local td = vector.distance(pos1, pos2) + + -- Actual Distance (ad) traveled + local ad = 0 + + -- It continues to advance in the line of sight in search of a real + -- obstruction which counts as 'normal' nodebox. + while minetest_registered_nodes[nn] + and minetest_registered_nodes[nn].walkable == false do + + -- Check if you can still move forward + if td < ad + stepsize then + return true -- Reached the target + end + + -- Moves the analyzed pos + local d = vector.distance(pos1, pos2) + + npos1.x = ((pos2.x - pos1.x) / d * stepsize) + pos1.x + npos1.y = ((pos2.y - pos1.y) / d * stepsize) + pos1.y + npos1.z = ((pos2.z - pos1.z) / d * stepsize) + pos1.z + + -- NaN checks + if d == 0 + or npos1.x ~= npos1.x + or npos1.y ~= npos1.y + or npos1.z ~= npos1.z then + return false + end + + ad = ad + stepsize + + -- scan again + r, pos = minetest_line_of_sight(npos1, pos2, stepsize) + + if r == true then return true end + + -- New Nodename found + nn = minetest_get_node(pos).name + + end + + return false +end + +-- Returns true if node is a water hazard +local is_node_waterhazard = function(self, nodename) + local nn = nodename + if self.water_damage > 0 then + if minetest_get_item_group(nn, "water") ~= 0 then + return true + end + end + if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].drowning and minetest_registered_nodes[nn].drowning > 0 then + if self.breath_max ~= -1 then + -- check if the mob is water-breathing _and_ the block is water; only return true if neither is the case + -- this will prevent water-breathing mobs to classify water or e.g. sand below them as dangerous + if not self.breathes_in_water and minetest_get_item_group(nn, "water") ~= 0 then + return true + end + end + end + return false +end + + +-- Returns true is node can deal damage to self +local is_node_dangerous = function(self, nodename) + local nn = nodename + if self.lava_damage > 0 then + if minetest_get_item_group(nn, "lava") ~= 0 then + return true + end + end + if self.fire_damage > 0 then + if minetest_get_item_group(nn, "fire") ~= 0 then + return true + end + end + if minetest_registered_nodes[nn] and minetest_registered_nodes[nn].damage_per_second and minetest_registered_nodes[nn].damage_per_second > 0 then + return true + end + return false +end + + +local add_texture_mod = function(self, mod) + local full_mod = "" + local already_added = false + for i=1, #self.texture_mods do + if mod == self.texture_mods[i] then + already_added = true + end + full_mod = full_mod .. self.texture_mods[i] + end + if not already_added then + full_mod = full_mod .. mod + table.insert(self.texture_mods, mod) + end + self.object:set_texture_mod(full_mod) +end + + +local remove_texture_mod = function(self, mod) + local full_mod = "" + local remove = {} + for i=1, #self.texture_mods do + if self.texture_mods[i] ~= mod then + full_mod = full_mod .. self.texture_mods[i] + else + table.insert(remove, i) + end + end + for i=#remove, 1 do + table.remove(self.texture_mods, remove[i]) + end + self.object:set_texture_mod(full_mod) +end From 54f5bee8a379bf910c1cc6ea3d33bd32b819f3dd Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 08:08:29 -0400 Subject: [PATCH 011/117] reorganize load settings --- mods/ENTITIES/mcl_mobs/api.lua | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 3619ca3628..18285e7f28 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -62,6 +62,18 @@ MOB_CAP.passive = 10 MOB_CAP.ambient = 15 MOB_CAP.water = 15 +-- Load settings +local damage_enabled = minetest_settings:get_bool("enable_damage") +local disable_blood = minetest_settings:get_bool("mobs_disable_blood") +local mobs_drop_items = minetest_settings:get_bool("mobs_drop_items") ~= false +local mobs_griefing = minetest_settings:get_bool("mobs_griefing") ~= false +local spawn_protected = minetest_settings:get_bool("mobs_spawn_protected") ~= false +local remove_far = true +local difficulty = tonumber(minetest_settings:get("mob_difficulty")) or 1.0 +local show_health = false +local max_per_block = tonumber(minetest_settings:get("max_objects_per_block") or 64) +local mobs_spawn_chance = tonumber(minetest_settings:get("mobs_spawn_chance") or 2.5) + -- random locals I found local los_switcher = false @@ -96,17 +108,7 @@ local atan = function(x) end --- Load settings -local damage_enabled = minetest_settings:get_bool("enable_damage") -local disable_blood = minetest_settings:get_bool("mobs_disable_blood") -local mobs_drop_items = minetest_settings:get_bool("mobs_drop_items") ~= false -local mobs_griefing = minetest_settings:get_bool("mobs_griefing") ~= false -local spawn_protected = minetest_settings:get_bool("mobs_spawn_protected") ~= false -local remove_far = true -local difficulty = tonumber(minetest_settings:get("mob_difficulty")) or 1.0 -local show_health = false -local max_per_block = tonumber(minetest_settings:get("max_objects_per_block") or 64) -local mobs_spawn_chance = tonumber(minetest_settings:get("mobs_spawn_chance") or 2.5) + -- Shows helpful debug info above each mob local mobs_debug = minetest_settings:get_bool("mobs_debug", false) From f29ad4b8b78689ed0d759c18178a6b2dbc9a1e25 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 08:20:11 -0400 Subject: [PATCH 012/117] Reorganize more settings to the top of file --- mods/ENTITIES/mcl_mobs/api.lua | 1187 +------------------------------- 1 file changed, 30 insertions(+), 1157 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 18285e7f28..9a32c394d5 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -62,7 +62,7 @@ MOB_CAP.passive = 10 MOB_CAP.ambient = 15 MOB_CAP.water = 15 --- Load settings +-- Load main settings local damage_enabled = minetest_settings:get_bool("enable_damage") local disable_blood = minetest_settings:get_bool("mobs_disable_blood") local mobs_drop_items = minetest_settings:get_bool("mobs_drop_items") ~= false @@ -74,12 +74,31 @@ local show_health = false local max_per_block = tonumber(minetest_settings:get("max_objects_per_block") or 64) local mobs_spawn_chance = tonumber(minetest_settings:get("mobs_spawn_chance") or 2.5) +-- pathfinding settings +local enable_pathfinding = true +local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching +local stuck_path_timeout = 10 -- how long will mob follow path before giving up + +-- default nodes +local node_ice = "mcl_core:ice" +local node_snowblock = "mcl_core:snowblock" +local node_snow = "mcl_core:snow" +mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" + +local mod_weather = minetest_get_modpath("mcl_weather") ~= nil +local mod_explosions = minetest_get_modpath("mcl_explosions") ~= nil +local mod_mobspawners = minetest_get_modpath("mcl_mobspawners") ~= nil +local mod_hunger = minetest_get_modpath("mcl_hunger") ~= nil +local mod_worlds = minetest_get_modpath("mcl_worlds") ~= nil +local mod_armor = minetest_get_modpath("mcl_armor") ~= nil +local mod_experience = minetest_get_modpath("mcl_experience") ~= nil + -- random locals I found -local los_switcher = false +local los_switcher = false local height_switcher = false --- Localize +-- Get translator local S = minetest.get_translator("mcl_mobs") -- CMI support check @@ -121,109 +140,6 @@ if minetest_settings:get_bool("only_peaceful_mobs", false) then end) end --- pathfinding settings -local enable_pathfinding = true -local stuck_timeout = 3 -- how long before mob gets stuck in place and starts searching -local stuck_path_timeout = 10 -- how long will mob follow path before giving up - --- default nodes -local node_ice = "mcl_core:ice" -local node_snowblock = "mcl_core:snowblock" -local node_snow = "mcl_core:snow" -mobs.fallback_node = minetest.registered_aliases["mapgen_dirt"] or "mcl_core:dirt" - -local mod_weather = minetest_get_modpath("mcl_weather") ~= nil -local mod_explosions = minetest_get_modpath("mcl_explosions") ~= nil -local mod_mobspawners = minetest_get_modpath("mcl_mobspawners") ~= nil -local mod_hunger = minetest_get_modpath("mcl_hunger") ~= nil -local mod_worlds = minetest_get_modpath("mcl_worlds") ~= nil -local mod_armor = minetest_get_modpath("mcl_armor") ~= nil -local mod_experience = minetest_get_modpath("mcl_experience") ~= nil - - - --- play sound -local mob_sound = function(self, soundname, is_opinion, fixed_pitch) - - local soundinfo - if self.sounds_child and self.child then - soundinfo = self.sounds_child - elseif self.sounds then - soundinfo = self.sounds - end - if not soundinfo then - return - end - local sound = soundinfo[soundname] - if sound then - if is_opinion and self.opinion_sound_cooloff > 0 then - return - end - local pitch - if not fixed_pitch then - local base_pitch = soundinfo.base_pitch - if not base_pitch then - base_pitch = 1 - end - if self.child and (not self.sounds_child) then - -- Children have higher pitch - pitch = base_pitch * 1.5 - else - pitch = base_pitch - end - -- randomize the pitch a bit - pitch = pitch + math_random(-10, 10) * 0.005 - end - minetest_sound_play(sound, { - object = self.object, - gain = 1.0, - max_hear_distance = self.sounds.distance, - pitch = pitch, - }, true) - self.opinion_sound_cooloff = 1 - end -end - --- Return true if object is in view_range -local function object_in_range(self, object) - if not object then - return false - end - local factor - -- Apply view range reduction for special player armor - if object:is_player() and mod_armor then - factor = armor:get_mob_view_range_factor(object, self.name) - end - -- Distance check - local dist - if factor and factor == 0 then - return false - elseif factor then - dist = self.view_range * factor - else - dist = self.view_range - end - - local p1, p2 = self.object:get_pos(), object:get_pos() - return p1 and p2 and (vector.distance(p1, p2) <= dist) -end - --- attack player/mob -local do_attack = function(self, player) - - if self.state == "attack" or self.state == "die" then - return - end - - self.attack = player - self.state = "attack" - - -- TODO: Implement war_cry sound without being annoying - --if math_random(0, 100) < 90 then - --mob_sound(self, "war_cry", true) - --end -end - local collision = function(self) pos = self.object:get_pos() --do collision detection from the base of the mob @@ -350,33 +266,6 @@ local get_velocity = function(self) return 0 end -local function update_roll(self) - local is_Fleckenstein = self.nametag == "Fleckenstein" - local was_Fleckenstein = false - - local rot = self.object:get_rotation() - rot.z = is_Fleckenstein and math_pi or 0 - self.object:set_rotation(rot) - - local cbox = table.copy(self.collisionbox) - local acbox = self.object:get_properties().collisionbox - - if math_abs(cbox[2] - acbox[2]) > 0.1 then - was_Fleckenstein = true - end - - if is_Fleckenstein ~= was_Fleckenstein then - local pos = self.object:get_pos() - pos.y = pos.y + (acbox[2] + acbox[5]) - self.object:set_pos(pos) - end - - if is_Fleckenstein then - cbox[2], cbox[5] = -cbox[5], -cbox[2] - end - - self.object:set_properties({collisionbox = cbox}) -end -- set and return valid yaw local set_yaw = function(self, yaw, delay, dtime) @@ -489,751 +378,14 @@ mobs.death_effect = function(pos, yaw, collisionbox, rotate) end --- check if within physical map limits (-30911 to 30927) -local within_limits, wmin, wmax = nil, -30913, 30928 -within_limits = function(pos, radius) - if mcl_vars then - if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then - wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max - within_limits = function(pos, radius) - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax - end - end - end - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax -end - - --- is mob facing a cliff or danger -local is_at_cliff_or_danger = function(self) - - if self.fear_height == 0 then -- 0 for no falling protection! - return false - end - - if not self.object:get_luaentity() then - return false - end - local yaw = self.object:get_yaw() - local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) - local pos = self.object:get_pos() - local ypos = pos.y + self.collisionbox[2] -- just above floor - - local free_fall, blocker = minetest_line_of_sight( - {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) - if free_fall then - return true - else - local bnode = minetest_get_node(blocker) - local danger = is_node_dangerous(self, bnode.name) - if danger then - return true - else - local def = minetest_registered_nodes[bnode.name] - if def and def.walkable then - return false - end - end - end - - return false -end - - --- copy the 'mob facing cliff_or_danger check' from above, and rework to avoid water -local is_at_water_danger = function(self) - - - if not self.object:get_luaentity() then - return false - end - local yaw = self.object:get_yaw() - local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) - local pos = self.object:get_pos() - local ypos = pos.y + self.collisionbox[2] -- just above floor - - local free_fall, blocker = minetest_line_of_sight( - {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, - {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) - if free_fall then - return true - else - local bnode = minetest_get_node(blocker) - local waterdanger = is_node_waterhazard(self, bnode.name) - if - waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) then - return false - elseif waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) == false then - return true - else - local def = minetest_registered_nodes[bnode.name] - if def and def.walkable then - return false - end - end - end - - return false -end - - --- get node but use fallback for nil or unknown -local node_ok = function(pos, fallback) - - fallback = fallback or mobs.fallback_node - - local node = minetest_get_node_or_nil(pos) - - if node and minetest_registered_nodes[node.name] then - return node - end - - return minetest_registered_nodes[fallback] -end - - --- environmental damage (water, lava, fire, light etc.) -local do_env_damage = function(self) - - -- feed/tame text timer (so mob 'full' messages dont spam chat) - if self.htimer > 0 then - self.htimer = self.htimer - 1 - end - - -- reset nametag after showing health stats - if self.htimer < 1 and self.nametag2 then - - self.nametag = self.nametag2 - self.nametag2 = nil - - update_tag(self) - end - - local pos = self.object:get_pos() - - self.time_of_day = minetest.get_timeofday() - - -- remove mob if beyond map limits - if not within_limits(pos, 0) then - mcl_burning.extinguish(self.object) - self.object:remove() - return true - end - - - -- Deal light damage to mob, returns true if mob died - local deal_light_damage = function(self, pos, damage) - if not (mod_weather and (mcl_weather.rain.raining or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos)) then - self.health = self.health - damage - - effect(pos, 5, "mcl_particles_smoke.png") - - if check_for_death(self, "light", {type = "light"}) then - return true - end - end - end - - -- Use get_node_light for Minetest version 5.3 where get_natural_light - -- does not exist yet. - local get_light = minetest_get_natural_light or minetest_get_node_light - local sunlight = get_light(pos, self.time_of_day) - - -- bright light harms mob - if self.light_damage ~= 0 and (sunlight or 0) > 12 then - if deal_light_damage(self, pos, self.light_damage) then - return true - end - end - local _, dim = nil, "overworld" - if mod_worlds then - _, dim = mcl_worlds.y_to_layer(pos.y) - end - if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (sunlight or 0) >= minetest.LIGHT_MAX and dim == "overworld" then - if self.ignited_by_sunlight then - mcl_burning.set_on_fire(self.object, 10) - else - deal_light_damage(self, pos, self.sunlight_damage) - return true - end - end - - local y_level = self.collisionbox[2] - - if self.child then - y_level = self.collisionbox[2] * 0.5 - end - - -- what is mob standing in? - pos.y = pos.y + y_level + 0.25 -- foot level - local pos2 = {x=pos.x, y=pos.y-1, z=pos.z} - self.standing_in = node_ok(pos, "air").name - self.standing_on = node_ok(pos2, "air").name - - -- don't fall when on ignore, just stand still - if self.standing_in == "ignore" then - self.object:set_velocity({x = 0, y = 0, z = 0}) - end - - local nodef = minetest_registered_nodes[self.standing_in] - - -- rain - if self.rain_damage > 0 and mod_weather then - if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then - - self.health = self.health - self.rain_damage - - if check_for_death(self, "rain", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - end - - pos.y = pos.y + 1 -- for particle effect position - - -- water damage - if self.water_damage > 0 - and nodef.groups.water then - - if self.water_damage ~= 0 then - - self.health = self.health - self.water_damage - - effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil) - - if check_for_death(self, "water", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- lava damage - elseif self.lava_damage > 0 - and (nodef.groups.lava) then - - if self.lava_damage ~= 0 then - - self.health = self.health - self.lava_damage - - effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) - - if check_for_death(self, "lava", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- fire damage - elseif self.fire_damage > 0 - and (nodef.groups.fire) then - - if self.fire_damage ~= 0 then - - self.health = self.health - self.fire_damage - - effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) - - if check_for_death(self, "fire", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- damage_per_second node check - elseif nodef.damage_per_second ~= 0 and not nodef.groups.lava and not nodef.groups.fire then - - self.health = self.health - nodef.damage_per_second - - effect(pos, 5, "mcl_particles_smoke.png") - - if check_for_death(self, "dps", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - - -- Drowning damage - if self.breath_max ~= -1 then - local drowning = false - if self.breathes_in_water then - if minetest_get_item_group(self.standing_in, "water") == 0 then - drowning = true - end - elseif nodef.drowning > 0 then - drowning = true - end - if drowning then - - self.breath = math_max(0, self.breath - 1) - - effect(pos, 2, "bubble.png", nil, nil, 1, nil) - if self.breath <= 0 then - local dmg - if nodef.drowning > 0 then - dmg = nodef.drowning - else - dmg = 4 - end - damage_effect(self, dmg) - self.health = self.health - dmg - end - if check_for_death(self, "drowning", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - else - self.breath = math_min(self.breath_max, self.breath + 1) - end - end - - --- suffocation inside solid node - -- FIXME: Redundant with mcl_playerplus - if (self.suffocation == true) - and (nodef.walkable == nil or nodef.walkable == true) - and (nodef.collision_box == nil or nodef.collision_box.type == "regular") - and (nodef.node_box == nil or nodef.node_box.type == "regular") - and (nodef.groups.disable_suffocation ~= 1) - and (nodef.groups.opaque == 1) then - - -- Short grace period before starting to take suffocation damage. - -- This is different from players, who take damage instantly. - -- This has been done because mobs might briefly be inside solid nodes - -- when e.g. climbing up stairs. - -- This is a bit hacky because it assumes that do_env_damage - -- is called roughly every second only. - self.suffocation_timer = self.suffocation_timer + 1 - if self.suffocation_timer >= 3 then - -- 2 damage per second - -- TODO: Deal this damage once every 1/2 second - self.health = self.health - 2 - - if check_for_death(self, "suffocation", {type = "environment", - pos = pos, node = self.standing_in}) then - return true - end - end - else - self.suffocation_timer = 0 - end - - return check_for_death(self, "", {type = "unknown"}) -end - - --- jump if facing a solid node (not fences or gates) -local do_jump = function(self) - - if not self.jump - or self.jump_height == 0 - or self.fly - or (self.child and self.type ~= "monster") - or self.order == "stand" then - return false - end - - self.facing_fence = false - - -- something stopping us while moving? - if self.state ~= "stand" - and get_velocity(self) > 0.5 - and self.object:get_velocity().y ~= 0 then - return false - end - - local pos = self.object:get_pos() - local yaw = self.object:get_yaw() - - -- what is mob standing on? - pos.y = pos.y + self.collisionbox[2] - 0.2 - - local nod = node_ok(pos) - - if minetest_registered_nodes[nod.name].walkable == false then - return false - end - - -- where is front - local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) - local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) - - -- what is in front of mob? - nod = node_ok({ - x = pos.x + dir_x, - y = pos.y + 0.5, - z = pos.z + dir_z - }) - - -- this is used to detect if there's a block on top of the block in front of the mob. - -- If there is, there is no point in jumping as we won't manage. - local nodTop = node_ok({ - x = pos.x + dir_x, - y = pos.y + 1.5, - z = pos.z + dir_z - }, "air") - - -- we don't attempt to jump if there's a stack of blocks blocking - if minetest_registered_nodes[nodTop.name].walkable == true then - return false - end - - -- thin blocks that do not need to be jumped - if nod.name == node_snow then - return false - end - - if self.walk_chance == 0 - or minetest_registered_items[nod.name].walkable then - - if minetest_get_item_group(nod.name, "fence") == 0 - and minetest_get_item_group(nod.name, "fence_gate") == 0 - and minetest_get_item_group(nod.name, "wall") == 0 then - - local v = self.object:get_velocity() - - v.y = self.jump_height - - set_animation(self, "jump") -- only when defined - - self.object:set_velocity(v) - - -- when in air move forward - minetest_after(0.3, function(self, v) - if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then - return - end - self.object:set_acceleration({ - x = v.x * 2, - y = -10, - z = v.z * 2, - }) - end, self, v) - - if self.jump_sound_cooloff <= 0 then - mob_sound(self, "jump") - self.jump_sound_cooloff = 0.5 - end - else - self.facing_fence = true - end - - -- if we jumped against a block/wall 4 times then turn - if self.object:get_velocity().x ~= 0 - and self.object:get_velocity().z ~= 0 then - - self.jump_count = (self.jump_count or 0) + 1 - - if self.jump_count == 4 then - - local yaw = self.object:get_yaw() or 0 - - yaw = set_yaw(self, yaw + 1.35, 8) - - self.jump_count = 0 - end - end - - return true - end - - return false -end - - --- blast damage to entities nearby -local entity_physics = function(pos, radius) - - radius = radius * 2 - - local objs = minetest_get_objects_inside_radius(pos, radius) - local obj_pos, dist - - for n = 1, #objs do - - obj_pos = objs[n]:get_pos() - - dist = vector.distance(pos, obj_pos) - if dist < 1 then dist = 1 end - - local damage = math_floor((4 / dist) * radius) - local ent = objs[n]:get_luaentity() - - -- punches work on entities AND players - objs[n]:punch(objs[n], 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = damage}, - }, pos) - end -end - - --- should mob follow what I'm holding ? -local follow_holding = function(self, clicker) - - if mobs.invis[clicker:get_player_name()] then - return false - end - - local item = clicker:get_wielded_item() - local t = type(self.follow) - - -- single item - if t == "string" - and item:get_name() == self.follow then - return true - - -- multiple items - elseif t == "table" then - - for no = 1, #self.follow do - - if self.follow[no] == item:get_name() then - return true - end - end - end - - return false -end - - --- find two animals of same type and breed if nearby and horny -local breed = function(self) - - -- child takes a long time before growing into adult - if self.child == true then - - -- When a child, hornytimer is used to count age until adulthood - self.hornytimer = self.hornytimer + 1 - - if self.hornytimer >= CHILD_GROW_TIME then - - self.child = false - self.hornytimer = 0 - - self.object:set_properties({ - textures = self.base_texture, - mesh = self.base_mesh, - visual_size = self.base_size, - collisionbox = self.base_colbox, - selectionbox = self.base_selbox, - }) - - -- custom function when child grows up - if self.on_grown then - self.on_grown(self) - else - -- jump when fully grown so as not to fall into ground - self.object:set_velocity({ - x = 0, - y = self.jump_height, - z = 0 - }) - end - end - - return - end - - -- horny animal can mate for BREED_TIME seconds, - -- afterwards horny animal cannot mate again for BREED_TIME_AGAIN seconds - if self.horny == true - and self.hornytimer < BREED_TIME + BREED_TIME_AGAIN then - - self.hornytimer = self.hornytimer + 1 - - if self.hornytimer >= BREED_TIME + BREED_TIME_AGAIN then - self.hornytimer = 0 - self.horny = false - end - end - - -- find another same animal who is also horny and mate if nearby - if self.horny == true - and self.hornytimer <= BREED_TIME then - - local pos = self.object:get_pos() - - effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) - - local objs = minetest_get_objects_inside_radius(pos, 3) - local num = 0 - local ent = nil - - for n = 1, #objs do - - ent = objs[n]:get_luaentity() - - -- check for same animal with different colour - local canmate = false - - if ent then - - if ent.name == self.name then - canmate = true - else - local entname = string.split(ent.name,":") - local selfname = string.split(self.name,":") - - if entname[1] == selfname[1] then - entname = string.split(entname[2],"_") - selfname = string.split(selfname[2],"_") - - if entname[1] == selfname[1] then - canmate = true - end - end - end - end - - if ent - and canmate == true - and ent.horny == true - and ent.hornytimer <= BREED_TIME then - num = num + 1 - end - - -- found your mate? then have a baby - if num > 1 then - - self.hornytimer = BREED_TIME + 1 - ent.hornytimer = BREED_TIME + 1 - - -- spawn baby - minetest_after(5, function(parent1, parent2, pos) - if not parent1.object:get_luaentity() then - return - end - if not parent2.object:get_luaentity() then - return - end - - -- Give XP - if mod_experience then - mcl_experience.throw_experience(pos, math_random(1, 7)) - end - - -- custom breed function - if parent1.on_breed then - -- when false, skip going any further - if parent1.on_breed(parent1, parent2) == false then - return - end - end - - local child = mobs:spawn_child(pos, parent1.name) - - local ent_c = child:get_luaentity() - - - -- Use texture of one of the parents - local p = math_random(1, 2) - if p == 1 then - ent_c.base_texture = parent1.base_texture - else - ent_c.base_texture = parent2.base_texture - end - child:set_properties({ - textures = ent_c.base_texture - }) - - -- tamed and owned by parents' owner - ent_c.tamed = true - ent_c.owner = parent1.owner - end, self, ent, pos) - - num = 0 - - break - end - end - end -end - - --- find and replace what mob is looking for (grass, wheat etc.) -local replace = function(self, pos) - - if not self.replace_rate - or not self.replace_what - or self.child == true - or self.object:get_velocity().y ~= 0 - or math_random(1, self.replace_rate) > 1 then - return - end - - local what, with, y_offset - - if type(self.replace_what[1]) == "table" then - - local num = math_random(#self.replace_what) - - what = self.replace_what[num][1] or "" - with = self.replace_what[num][2] or "" - y_offset = self.replace_what[num][3] or 0 - else - what = self.replace_what - with = self.replace_with or "" - y_offset = self.replace_offset or 0 - end - - pos.y = pos.y + y_offset - - local node = minetest_get_node(pos) - if node.name == what then - - local oldnode = {name = what, param2 = node.param2} - local newnode = {name = with, param2 = node.param2} - local on_replace_return - - if self.on_replace then - on_replace_return = self.on_replace(self, pos, oldnode, newnode) - end - - if on_replace_return ~= false then - - if mobs_griefing then - minetest_set_node(pos, newnode) - end - - end - end -end - - --- check if daytime and also if mob is docile during daylight hours -local day_docile = function(self) - - if self.docile_by_day == false then - - return false - - elseif self.docile_by_day == true - and self.time_of_day > 0.2 - and self.time_of_day < 0.8 then - - return true - end -end - - - - -- execute current state (stand, walk, run, attacks) -- returns true if mob has died local do_states = function(self, dtime) local yaw = self.object:get_yaw() or 0 + --[[ + if self.state == "stand" then if math_random(1, 4) == 1 then @@ -1785,290 +937,10 @@ local do_states = function(self, dtime) end end end + ]]-- end --- deal damage and effects when mob punched -local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) - -- custom punch function - if self.do_punch then - - -- when false skip going any further - if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then - return - end - end - - -- error checking when mod profiling is enabled - if not tool_capabilities then - minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") - return - end - - local is_player = hitter:is_player() - - if is_player then - -- is mob protected? - if self.protected and minetest_is_protected(self.object:get_pos(), hitter:get_player_name()) then - return - end - - -- set/update 'drop xp' timestamp if hitted by player - self.xp_timestamp = minetest_get_us_time() - end - - - -- punch interval - local weapon = hitter:get_wielded_item() - local punch_interval = 1.4 - - -- exhaust attacker - if mod_hunger and is_player then - mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) - end - - -- calculate mob damage - local damage = 0 - local armor = self.object:get_armor_groups() or {} - local tmp - - -- quick error check incase it ends up 0 (serialize.h check test) - if tflp == 0 then - tflp = 0.2 - end - - if use_cmi then - damage = cmi.calculate_damage(self.object, hitter, tflp, tool_capabilities, dir) - else - - for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do - - tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) - - if tmp < 0 then - tmp = 0.0 - elseif tmp > 1 then - tmp = 1.0 - end - - damage = damage + (tool_capabilities.damage_groups[group] or 0) - * tmp * ((armor[group] or 0) / 100.0) - end - end - - if weapon then - local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") - if fire_aspect_level > 0 then - mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) - end - end - - -- check for tool immunity or special damage - for n = 1, #self.immune_to do - - if self.immune_to[n][1] == weapon:get_name() then - - damage = self.immune_to[n][2] or 0 - break - end - end - - -- healing - if damage <= -1 then - self.health = self.health - math_floor(damage) - return - end - - if use_cmi then - - local cancel = cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) - - if cancel then return end - end - - if tool_capabilities then - punch_interval = tool_capabilities.full_punch_interval or 1.4 - end - - -- add weapon wear manually - -- Required because we have custom health handling ("health" property) - if minetest_is_creative_enabled("") ~= true - and tool_capabilities then - if tool_capabilities.punch_attack_uses then - -- Without this delay, the wear does not work. Quite hacky ... - minetest_after(0, function(name) - local player = minetest.get_player_by_name(name) - if not player then return end - local weapon = hitter:get_wielded_item(player) - local def = weapon:get_definition() - if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then - local wear = math_floor(65535/tool_capabilities.punch_attack_uses) - weapon:add_wear(wear) - hitter:set_wielded_item(weapon) - end - end, hitter:get_player_name()) - end - end - - local die = false - - -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. - if damage >= 0.1 then - - -- weapon sounds - if weapon:get_definition().sounds ~= nil then - - local s = math_random(0, #weapon:get_definition().sounds) - - minetest_sound_play(weapon:get_definition().sounds[s], { - object = self.object, --hitter, - max_hear_distance = 8 - }, true) - else - minetest_sound_play("default_punch", { - object = self.object, - max_hear_distance = 5 - }, true) - end - - damage_effect(self, damage) - - -- do damage - self.health = self.health - damage - - -- skip future functions if dead, except alerting others - if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then - die = true - end - - -- knock back effect (only on full punch) - if not die - and self.knock_back - and tflp >= punch_interval then - - local v = self.object:get_velocity() - local r = 1.4 - math_min(punch_interval, 1.4) - local kb = r * 2.0 - local up = 2 - - -- if already in air then dont go up anymore when hit - if v.y ~= 0 - or self.fly then - up = 0 - end - - -- direction error check - dir = dir or {x = 0, y = 0, z = 0} - - -- check if tool already has specific knockback value - if tool_capabilities.damage_groups["knockback"] then - kb = tool_capabilities.damage_groups["knockback"] - else - kb = kb * 1.5 - end - - - local luaentity - if hitter then - luaentity = hitter:get_luaentity() - end - if hitter and is_player then - local wielditem = hitter:get_wielded_item() - kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") - elseif luaentity and luaentity._knockback then - kb = kb + luaentity._knockback - end - - self.object:set_velocity({ - x = dir.x * kb, - y = dir.y * kb + up * 2, - z = dir.z * kb - }) - - self.pause_timer = 0.25 - end - end -- END if damage - - -- if skittish then run away - if not die and self.runaway == true and self.state ~= "flop" then - - local lp = hitter:get_pos() - local s = self.object:get_pos() - local vec = { - x = lp.x - s.x, - y = lp.y - s.y, - z = lp.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate - - if lp.x > s.x then - yaw = yaw + math_pi - end - - yaw = set_yaw(self, yaw, 6) - self.state = "runaway" - self.runaway_timer = 0 - self.following = nil - end - - local name = hitter:get_player_name() or "" - - -- attack puncher and call other mobs for help - if self.passive == false - and self.state ~= "flop" - and (self.child == false or self.type == "monster") - and hitter:get_player_name() ~= self.owner - and not mobs.invis[ name ] then - - if not die then - -- attack whoever punched mob - self.state = "" - do_attack(self, hitter) - end - - -- alert others to the attack - local objs = minetest_get_objects_inside_radius(hitter:get_pos(), self.view_range) - local obj = nil - - for n = 1, #objs do - - obj = objs[n]:get_luaentity() - - if obj then - - -- only alert members of same mob or friends - if obj.group_attack - and obj.state ~= "attack" - and obj.owner ~= name then - if obj.name == self.name then - do_attack(obj, hitter) - elseif type(obj.group_attack) == "table" then - for i=1, #obj.group_attack do - if obj.name == obj.group_attack[i] then - do_attack(obj, hitter) - break - end - end - end - end - - -- have owned mobs attack player threat - if obj.owner == name and obj.owner_loyal then - do_attack(obj, self.object) - end - end - end - end -end - -local mob_detach_child = function(self, child) - - if self.driver == child then - self.driver = nil - end - -end -- get entity staticdata local mob_staticdata = function(self) @@ -2260,8 +1132,9 @@ local mob_activate = function(self, staticdata, def, dtime) -- set anything changed above self.object:set_properties(self) set_yaw(self, (math_random(0, 360) - 180) / 180 * math_pi, 6) - update_tag(self) - set_animation(self, "stand") + + --update_tag(self) + --set_animation(self, "stand") -- run on_spawn function if found if self.on_spawn and not self.on_spawn_run then @@ -2370,7 +1243,7 @@ local mob_step = function(self, dtime) yaw = yaw + (math_random() * 2 - 1) * 5 * dtime end self.object:set_yaw(yaw) - update_roll(self) + --update_roll(self) end -- end rotation @@ -2974,7 +1847,7 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative) end if pos - and within_limits(pos, 0) + --and within_limits(pos, 0) and not minetest_is_protected(pos, placer:get_player_name()) then local name = placer:get_player_name() From 9758bbf2e7e382948b4ad1ab8c360519270fec14 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 08:21:04 -0400 Subject: [PATCH 013/117] Finish gutting mob api --- mods/ENTITIES/mcl_mobs/backup_code_api.lua | 1130 ++++++++++++++++++++ 1 file changed, 1130 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/backup_code_api.lua index ba4b8452af..85cf0db5f0 100644 --- a/mods/ENTITIES/mcl_mobs/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/backup_code_api.lua @@ -1464,3 +1464,1133 @@ local remove_texture_mod = function(self, mod) end self.object:set_texture_mod(full_mod) end + + +-- Return true if object is in view_range +local function object_in_range(self, object) + if not object then + return false + end + local factor + -- Apply view range reduction for special player armor + if object:is_player() and mod_armor then + factor = armor:get_mob_view_range_factor(object, self.name) + end + -- Distance check + local dist + if factor and factor == 0 then + return false + elseif factor then + dist = self.view_range * factor + else + dist = self.view_range + end + + local p1, p2 = self.object:get_pos(), object:get_pos() + return p1 and p2 and (vector.distance(p1, p2) <= dist) +end + +-- attack player/mob +local do_attack = function(self, player) + + if self.state == "attack" or self.state == "die" then + return + end + + self.attack = player + self.state = "attack" + + -- TODO: Implement war_cry sound without being annoying + --if math_random(0, 100) < 90 then + --mob_sound(self, "war_cry", true) + --end +end + + +-- play sound +local mob_sound = function(self, soundname, is_opinion, fixed_pitch) + local soundinfo + if self.sounds_child and self.child then + soundinfo = self.sounds_child + elseif self.sounds then + soundinfo = self.sounds + end + if not soundinfo then + return + end + local sound = soundinfo[soundname] + if sound then + if is_opinion and self.opinion_sound_cooloff > 0 then + return + end + local pitch + if not fixed_pitch then + local base_pitch = soundinfo.base_pitch + if not base_pitch then + base_pitch = 1 + end + if self.child and (not self.sounds_child) then + -- Children have higher pitch + pitch = base_pitch * 1.5 + else + pitch = base_pitch + end + -- randomize the pitch a bit + pitch = pitch + math_random(-10, 10) * 0.005 + end + minetest_sound_play(sound, { + object = self.object, + gain = 1.0, + max_hear_distance = self.sounds.distance, + pitch = pitch, + }, true) + self.opinion_sound_cooloff = 1 + end +end + + +local function update_roll(self) + local is_Fleckenstein = self.nametag == "Fleckenstein" + local was_Fleckenstein = false + + local rot = self.object:get_rotation() + rot.z = is_Fleckenstein and math_pi or 0 + self.object:set_rotation(rot) + + local cbox = table.copy(self.collisionbox) + local acbox = self.object:get_properties().collisionbox + + if math_abs(cbox[2] - acbox[2]) > 0.1 then + was_Fleckenstein = true + end + + if is_Fleckenstein ~= was_Fleckenstein then + local pos = self.object:get_pos() + pos.y = pos.y + (acbox[2] + acbox[5]) + self.object:set_pos(pos) + end + + if is_Fleckenstein then + cbox[2], cbox[5] = -cbox[5], -cbox[2] + end + + self.object:set_properties({collisionbox = cbox}) +end + +-- check if within physical map limits (-30911 to 30927) +local within_limits, wmin, wmax = nil, -30913, 30928 +within_limits = function(pos, radius) + if mcl_vars then + if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then + wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max + within_limits = function(pos, radius) + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax + end + end + end + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax +end + +-- is mob facing a cliff or danger +local is_at_cliff_or_danger = function(self) + + if self.fear_height == 0 then -- 0 for no falling protection! + return false + end + + if not self.object:get_luaentity() then + return false + end + local yaw = self.object:get_yaw() + local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) + local pos = self.object:get_pos() + local ypos = pos.y + self.collisionbox[2] -- just above floor + + local free_fall, blocker = minetest_line_of_sight( + {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, + {x = pos.x + dir_x, y = ypos - self.fear_height, z = pos.z + dir_z}) + if free_fall then + return true + else + local bnode = minetest_get_node(blocker) + local danger = is_node_dangerous(self, bnode.name) + if danger then + return true + else + local def = minetest_registered_nodes[bnode.name] + if def and def.walkable then + return false + end + end + end + + return false +end + + +-- copy the 'mob facing cliff_or_danger check' from above, and rework to avoid water +local is_at_water_danger = function(self) + + + if not self.object:get_luaentity() then + return false + end + local yaw = self.object:get_yaw() + local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) + local pos = self.object:get_pos() + local ypos = pos.y + self.collisionbox[2] -- just above floor + + local free_fall, blocker = minetest_line_of_sight( + {x = pos.x + dir_x, y = ypos, z = pos.z + dir_z}, + {x = pos.x + dir_x, y = ypos - 3, z = pos.z + dir_z}) + if free_fall then + return true + else + local bnode = minetest_get_node(blocker) + local waterdanger = is_node_waterhazard(self, bnode.name) + if + waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) then + return false + elseif waterdanger and (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) == false then + return true + else + local def = minetest_registered_nodes[bnode.name] + if def and def.walkable then + return false + end + end + end + + return false +end + + +-- get node but use fallback for nil or unknown +local node_ok = function(pos, fallback) + + fallback = fallback or mobs.fallback_node + + local node = minetest_get_node_or_nil(pos) + + if node and minetest_registered_nodes[node.name] then + return node + end + + return minetest_registered_nodes[fallback] +end + + +-- environmental damage (water, lava, fire, light etc.) +local do_env_damage = function(self) + + -- feed/tame text timer (so mob 'full' messages dont spam chat) + if self.htimer > 0 then + self.htimer = self.htimer - 1 + end + + -- reset nametag after showing health stats + if self.htimer < 1 and self.nametag2 then + + self.nametag = self.nametag2 + self.nametag2 = nil + + update_tag(self) + end + + local pos = self.object:get_pos() + + self.time_of_day = minetest.get_timeofday() + + -- remove mob if beyond map limits + if not within_limits(pos, 0) then + mcl_burning.extinguish(self.object) + self.object:remove() + return true + end + + + -- Deal light damage to mob, returns true if mob died + local deal_light_damage = function(self, pos, damage) + if not (mod_weather and (mcl_weather.rain.raining or mcl_weather.state == "snow") and mcl_weather.is_outdoor(pos)) then + self.health = self.health - damage + + effect(pos, 5, "mcl_particles_smoke.png") + + if check_for_death(self, "light", {type = "light"}) then + return true + end + end + end + + -- Use get_node_light for Minetest version 5.3 where get_natural_light + -- does not exist yet. + local get_light = minetest_get_natural_light or minetest_get_node_light + local sunlight = get_light(pos, self.time_of_day) + + -- bright light harms mob + if self.light_damage ~= 0 and (sunlight or 0) > 12 then + if deal_light_damage(self, pos, self.light_damage) then + return true + end + end + local _, dim = nil, "overworld" + if mod_worlds then + _, dim = mcl_worlds.y_to_layer(pos.y) + end + if (self.sunlight_damage ~= 0 or self.ignited_by_sunlight) and (sunlight or 0) >= minetest.LIGHT_MAX and dim == "overworld" then + if self.ignited_by_sunlight then + mcl_burning.set_on_fire(self.object, 10) + else + deal_light_damage(self, pos, self.sunlight_damage) + return true + end + end + + local y_level = self.collisionbox[2] + + if self.child then + y_level = self.collisionbox[2] * 0.5 + end + + -- what is mob standing in? + pos.y = pos.y + y_level + 0.25 -- foot level + local pos2 = {x=pos.x, y=pos.y-1, z=pos.z} + self.standing_in = node_ok(pos, "air").name + self.standing_on = node_ok(pos2, "air").name + + -- don't fall when on ignore, just stand still + if self.standing_in == "ignore" then + self.object:set_velocity({x = 0, y = 0, z = 0}) + end + + local nodef = minetest_registered_nodes[self.standing_in] + + -- rain + if self.rain_damage > 0 and mod_weather then + if mcl_weather.rain.raining and mcl_weather.is_outdoor(pos) then + + self.health = self.health - self.rain_damage + + if check_for_death(self, "rain", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + end + + pos.y = pos.y + 1 -- for particle effect position + + -- water damage + if self.water_damage > 0 + and nodef.groups.water then + + if self.water_damage ~= 0 then + + self.health = self.health - self.water_damage + + effect(pos, 5, "mcl_particles_smoke.png", nil, nil, 1, nil) + + if check_for_death(self, "water", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- lava damage + elseif self.lava_damage > 0 + and (nodef.groups.lava) then + + if self.lava_damage ~= 0 then + + self.health = self.health - self.lava_damage + + effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) + + if check_for_death(self, "lava", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- fire damage + elseif self.fire_damage > 0 + and (nodef.groups.fire) then + + if self.fire_damage ~= 0 then + + self.health = self.health - self.fire_damage + + effect(pos, 5, "fire_basic_flame.png", nil, nil, 1, nil) + + if check_for_death(self, "fire", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- damage_per_second node check + elseif nodef.damage_per_second ~= 0 and not nodef.groups.lava and not nodef.groups.fire then + + self.health = self.health - nodef.damage_per_second + + effect(pos, 5, "mcl_particles_smoke.png") + + if check_for_death(self, "dps", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + + -- Drowning damage + if self.breath_max ~= -1 then + local drowning = false + if self.breathes_in_water then + if minetest_get_item_group(self.standing_in, "water") == 0 then + drowning = true + end + elseif nodef.drowning > 0 then + drowning = true + end + if drowning then + + self.breath = math_max(0, self.breath - 1) + + effect(pos, 2, "bubble.png", nil, nil, 1, nil) + if self.breath <= 0 then + local dmg + if nodef.drowning > 0 then + dmg = nodef.drowning + else + dmg = 4 + end + damage_effect(self, dmg) + self.health = self.health - dmg + end + if check_for_death(self, "drowning", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + else + self.breath = math_min(self.breath_max, self.breath + 1) + end + end + + --- suffocation inside solid node + -- FIXME: Redundant with mcl_playerplus + if (self.suffocation == true) + and (nodef.walkable == nil or nodef.walkable == true) + and (nodef.collision_box == nil or nodef.collision_box.type == "regular") + and (nodef.node_box == nil or nodef.node_box.type == "regular") + and (nodef.groups.disable_suffocation ~= 1) + and (nodef.groups.opaque == 1) then + + -- Short grace period before starting to take suffocation damage. + -- This is different from players, who take damage instantly. + -- This has been done because mobs might briefly be inside solid nodes + -- when e.g. climbing up stairs. + -- This is a bit hacky because it assumes that do_env_damage + -- is called roughly every second only. + self.suffocation_timer = self.suffocation_timer + 1 + if self.suffocation_timer >= 3 then + -- 2 damage per second + -- TODO: Deal this damage once every 1/2 second + self.health = self.health - 2 + + if check_for_death(self, "suffocation", {type = "environment", + pos = pos, node = self.standing_in}) then + return true + end + end + else + self.suffocation_timer = 0 + end + + return check_for_death(self, "", {type = "unknown"}) +end + + +-- jump if facing a solid node (not fences or gates) +local do_jump = function(self) + + if not self.jump + or self.jump_height == 0 + or self.fly + or (self.child and self.type ~= "monster") + or self.order == "stand" then + return false + end + + self.facing_fence = false + + -- something stopping us while moving? + if self.state ~= "stand" + and get_velocity(self) > 0.5 + and self.object:get_velocity().y ~= 0 then + return false + end + + local pos = self.object:get_pos() + local yaw = self.object:get_yaw() + + -- what is mob standing on? + pos.y = pos.y + self.collisionbox[2] - 0.2 + + local nod = node_ok(pos) + + if minetest_registered_nodes[nod.name].walkable == false then + return false + end + + -- where is front + local dir_x = -math_sin(yaw) * (self.collisionbox[4] + 0.5) + local dir_z = math_cos(yaw) * (self.collisionbox[4] + 0.5) + + -- what is in front of mob? + nod = node_ok({ + x = pos.x + dir_x, + y = pos.y + 0.5, + z = pos.z + dir_z + }) + + -- this is used to detect if there's a block on top of the block in front of the mob. + -- If there is, there is no point in jumping as we won't manage. + local nodTop = node_ok({ + x = pos.x + dir_x, + y = pos.y + 1.5, + z = pos.z + dir_z + }, "air") + + -- we don't attempt to jump if there's a stack of blocks blocking + if minetest_registered_nodes[nodTop.name].walkable == true then + return false + end + + -- thin blocks that do not need to be jumped + if nod.name == node_snow then + return false + end + + if self.walk_chance == 0 + or minetest_registered_items[nod.name].walkable then + + if minetest_get_item_group(nod.name, "fence") == 0 + and minetest_get_item_group(nod.name, "fence_gate") == 0 + and minetest_get_item_group(nod.name, "wall") == 0 then + + local v = self.object:get_velocity() + + v.y = self.jump_height + + set_animation(self, "jump") -- only when defined + + self.object:set_velocity(v) + + -- when in air move forward + minetest_after(0.3, function(self, v) + if (not self.object) or (not self.object:get_luaentity()) or (self.state == "die") then + return + end + self.object:set_acceleration({ + x = v.x * 2, + y = -10, + z = v.z * 2, + }) + end, self, v) + + if self.jump_sound_cooloff <= 0 then + mob_sound(self, "jump") + self.jump_sound_cooloff = 0.5 + end + else + self.facing_fence = true + end + + -- if we jumped against a block/wall 4 times then turn + if self.object:get_velocity().x ~= 0 + and self.object:get_velocity().z ~= 0 then + + self.jump_count = (self.jump_count or 0) + 1 + + if self.jump_count == 4 then + + local yaw = self.object:get_yaw() or 0 + + yaw = set_yaw(self, yaw + 1.35, 8) + + self.jump_count = 0 + end + end + + return true + end + + return false +end + + +-- blast damage to entities nearby +local entity_physics = function(pos, radius) + + radius = radius * 2 + + local objs = minetest_get_objects_inside_radius(pos, radius) + local obj_pos, dist + + for n = 1, #objs do + + obj_pos = objs[n]:get_pos() + + dist = vector.distance(pos, obj_pos) + if dist < 1 then dist = 1 end + + local damage = math_floor((4 / dist) * radius) + local ent = objs[n]:get_luaentity() + + -- punches work on entities AND players + objs[n]:punch(objs[n], 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, pos) + end +end + + +-- should mob follow what I'm holding ? +local follow_holding = function(self, clicker) + + if mobs.invis[clicker:get_player_name()] then + return false + end + + local item = clicker:get_wielded_item() + local t = type(self.follow) + + -- single item + if t == "string" + and item:get_name() == self.follow then + return true + + -- multiple items + elseif t == "table" then + + for no = 1, #self.follow do + + if self.follow[no] == item:get_name() then + return true + end + end + end + + return false +end + + +-- find two animals of same type and breed if nearby and horny +local breed = function(self) + + -- child takes a long time before growing into adult + if self.child == true then + + -- When a child, hornytimer is used to count age until adulthood + self.hornytimer = self.hornytimer + 1 + + if self.hornytimer >= CHILD_GROW_TIME then + + self.child = false + self.hornytimer = 0 + + self.object:set_properties({ + textures = self.base_texture, + mesh = self.base_mesh, + visual_size = self.base_size, + collisionbox = self.base_colbox, + selectionbox = self.base_selbox, + }) + + -- custom function when child grows up + if self.on_grown then + self.on_grown(self) + else + -- jump when fully grown so as not to fall into ground + self.object:set_velocity({ + x = 0, + y = self.jump_height, + z = 0 + }) + end + end + + return + end + + -- horny animal can mate for BREED_TIME seconds, + -- afterwards horny animal cannot mate again for BREED_TIME_AGAIN seconds + if self.horny == true + and self.hornytimer < BREED_TIME + BREED_TIME_AGAIN then + + self.hornytimer = self.hornytimer + 1 + + if self.hornytimer >= BREED_TIME + BREED_TIME_AGAIN then + self.hornytimer = 0 + self.horny = false + end + end + + -- find another same animal who is also horny and mate if nearby + if self.horny == true + and self.hornytimer <= BREED_TIME then + + local pos = self.object:get_pos() + + effect({x = pos.x, y = pos.y + 1, z = pos.z}, 8, "heart.png", 3, 4, 1, 0.1) + + local objs = minetest_get_objects_inside_radius(pos, 3) + local num = 0 + local ent = nil + + for n = 1, #objs do + + ent = objs[n]:get_luaentity() + + -- check for same animal with different colour + local canmate = false + + if ent then + + if ent.name == self.name then + canmate = true + else + local entname = string.split(ent.name,":") + local selfname = string.split(self.name,":") + + if entname[1] == selfname[1] then + entname = string.split(entname[2],"_") + selfname = string.split(selfname[2],"_") + + if entname[1] == selfname[1] then + canmate = true + end + end + end + end + + if ent + and canmate == true + and ent.horny == true + and ent.hornytimer <= BREED_TIME then + num = num + 1 + end + + -- found your mate? then have a baby + if num > 1 then + + self.hornytimer = BREED_TIME + 1 + ent.hornytimer = BREED_TIME + 1 + + -- spawn baby + minetest_after(5, function(parent1, parent2, pos) + if not parent1.object:get_luaentity() then + return + end + if not parent2.object:get_luaentity() then + return + end + + -- Give XP + if mod_experience then + mcl_experience.throw_experience(pos, math_random(1, 7)) + end + + -- custom breed function + if parent1.on_breed then + -- when false, skip going any further + if parent1.on_breed(parent1, parent2) == false then + return + end + end + + local child = mobs:spawn_child(pos, parent1.name) + + local ent_c = child:get_luaentity() + + + -- Use texture of one of the parents + local p = math_random(1, 2) + if p == 1 then + ent_c.base_texture = parent1.base_texture + else + ent_c.base_texture = parent2.base_texture + end + child:set_properties({ + textures = ent_c.base_texture + }) + + -- tamed and owned by parents' owner + ent_c.tamed = true + ent_c.owner = parent1.owner + end, self, ent, pos) + + num = 0 + + break + end + end + end +end + +-- find and replace what mob is looking for (grass, wheat etc.) +local replace = function(self, pos) + + if not self.replace_rate + or not self.replace_what + or self.child == true + or self.object:get_velocity().y ~= 0 + or math_random(1, self.replace_rate) > 1 then + return + end + + local what, with, y_offset + + if type(self.replace_what[1]) == "table" then + + local num = math_random(#self.replace_what) + + what = self.replace_what[num][1] or "" + with = self.replace_what[num][2] or "" + y_offset = self.replace_what[num][3] or 0 + else + what = self.replace_what + with = self.replace_with or "" + y_offset = self.replace_offset or 0 + end + + pos.y = pos.y + y_offset + + local node = minetest_get_node(pos) + if node.name == what then + + local oldnode = {name = what, param2 = node.param2} + local newnode = {name = with, param2 = node.param2} + local on_replace_return + + if self.on_replace then + on_replace_return = self.on_replace(self, pos, oldnode, newnode) + end + + if on_replace_return ~= false then + + if mobs_griefing then + minetest_set_node(pos, newnode) + end + + end + end +end + + +-- check if daytime and also if mob is docile during daylight hours +local day_docile = function(self) + + if self.docile_by_day == false then + + return false + + elseif self.docile_by_day == true + and self.time_of_day > 0.2 + and self.time_of_day < 0.8 then + + return true + end +end + + +-- deal damage and effects when mob punched +local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) + + -- custom punch function + if self.do_punch then + + -- when false skip going any further + if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then + return + end + end + + -- error checking when mod profiling is enabled + if not tool_capabilities then + minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") + return + end + + local is_player = hitter:is_player() + + if is_player then + -- is mob protected? + if self.protected and minetest_is_protected(self.object:get_pos(), hitter:get_player_name()) then + return + end + + -- set/update 'drop xp' timestamp if hitted by player + self.xp_timestamp = minetest_get_us_time() + end + + + -- punch interval + local weapon = hitter:get_wielded_item() + local punch_interval = 1.4 + + -- exhaust attacker + if mod_hunger and is_player then + mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) + end + + -- calculate mob damage + local damage = 0 + local armor = self.object:get_armor_groups() or {} + local tmp + + -- quick error check incase it ends up 0 (serialize.h check test) + if tflp == 0 then + tflp = 0.2 + end + + if use_cmi then + damage = cmi.calculate_damage(self.object, hitter, tflp, tool_capabilities, dir) + else + + for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do + + tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) + + if tmp < 0 then + tmp = 0.0 + elseif tmp > 1 then + tmp = 1.0 + end + + damage = damage + (tool_capabilities.damage_groups[group] or 0) + * tmp * ((armor[group] or 0) / 100.0) + end + end + + if weapon then + local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") + if fire_aspect_level > 0 then + mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) + end + end + + -- check for tool immunity or special damage + for n = 1, #self.immune_to do + + if self.immune_to[n][1] == weapon:get_name() then + + damage = self.immune_to[n][2] or 0 + break + end + end + + -- healing + if damage <= -1 then + self.health = self.health - math_floor(damage) + return + end + + if use_cmi then + + local cancel = cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) + + if cancel then return end + end + + if tool_capabilities then + punch_interval = tool_capabilities.full_punch_interval or 1.4 + end + + -- add weapon wear manually + -- Required because we have custom health handling ("health" property) + if minetest_is_creative_enabled("") ~= true + and tool_capabilities then + if tool_capabilities.punch_attack_uses then + -- Without this delay, the wear does not work. Quite hacky ... + minetest_after(0, function(name) + local player = minetest.get_player_by_name(name) + if not player then return end + local weapon = hitter:get_wielded_item(player) + local def = weapon:get_definition() + if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then + local wear = math_floor(65535/tool_capabilities.punch_attack_uses) + weapon:add_wear(wear) + hitter:set_wielded_item(weapon) + end + end, hitter:get_player_name()) + end + end + + local die = false + + -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. + if damage >= 0.1 then + + -- weapon sounds + if weapon:get_definition().sounds ~= nil then + + local s = math_random(0, #weapon:get_definition().sounds) + + minetest_sound_play(weapon:get_definition().sounds[s], { + object = self.object, --hitter, + max_hear_distance = 8 + }, true) + else + minetest_sound_play("default_punch", { + object = self.object, + max_hear_distance = 5 + }, true) + end + + damage_effect(self, damage) + + -- do damage + self.health = self.health - damage + + -- skip future functions if dead, except alerting others + if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then + die = true + end + + -- knock back effect (only on full punch) + if not die + and self.knock_back + and tflp >= punch_interval then + + local v = self.object:get_velocity() + local r = 1.4 - math_min(punch_interval, 1.4) + local kb = r * 2.0 + local up = 2 + + -- if already in air then dont go up anymore when hit + if v.y ~= 0 + or self.fly then + up = 0 + end + + -- direction error check + dir = dir or {x = 0, y = 0, z = 0} + + -- check if tool already has specific knockback value + if tool_capabilities.damage_groups["knockback"] then + kb = tool_capabilities.damage_groups["knockback"] + else + kb = kb * 1.5 + end + + + local luaentity + if hitter then + luaentity = hitter:get_luaentity() + end + if hitter and is_player then + local wielditem = hitter:get_wielded_item() + kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + elseif luaentity and luaentity._knockback then + kb = kb + luaentity._knockback + end + + self.object:set_velocity({ + x = dir.x * kb, + y = dir.y * kb + up * 2, + z = dir.z * kb + }) + + self.pause_timer = 0.25 + end + end -- END if damage + + -- if skittish then run away + if not die and self.runaway == true and self.state ~= "flop" then + + local lp = hitter:get_pos() + local s = self.object:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + math_pi + end + + yaw = set_yaw(self, yaw, 6) + self.state = "runaway" + self.runaway_timer = 0 + self.following = nil + end + + local name = hitter:get_player_name() or "" + + -- attack puncher and call other mobs for help + if self.passive == false + and self.state ~= "flop" + and (self.child == false or self.type == "monster") + and hitter:get_player_name() ~= self.owner + and not mobs.invis[ name ] then + + if not die then + -- attack whoever punched mob + self.state = "" + do_attack(self, hitter) + end + + -- alert others to the attack + local objs = minetest_get_objects_inside_radius(hitter:get_pos(), self.view_range) + local obj = nil + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj then + + -- only alert members of same mob or friends + if obj.group_attack + and obj.state ~= "attack" + and obj.owner ~= name then + if obj.name == self.name then + do_attack(obj, hitter) + elseif type(obj.group_attack) == "table" then + for i=1, #obj.group_attack do + if obj.name == obj.group_attack[i] then + do_attack(obj, hitter) + break + end + end + end + end + + -- have owned mobs attack player threat + if obj.owner == name and obj.owner_loyal then + do_attack(obj, self.object) + end + end + end + end +end + +local mob_detach_child = function(self, child) + + if self.driver == child then + self.driver = nil + end + +end \ No newline at end of file From 220d30df5f159d69be22663733feb1fbf51c45f8 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 19:13:29 -0400 Subject: [PATCH 014/117] Completely gut do_states --- mods/ENTITIES/mcl_mobs/api.lua | 553 -------------------- mods/ENTITIES/mcl_mobs/backup_code_api.lua | 557 ++++++++++++++++++++- 2 files changed, 556 insertions(+), 554 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 9a32c394d5..6cc81aeb83 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -384,560 +384,7 @@ local do_states = function(self, dtime) local yaw = self.object:get_yaw() or 0 - --[[ - if self.state == "stand" then - - if math_random(1, 4) == 1 then - - local lp = nil - local s = self.object:get_pos() - local objs = minetest_get_objects_inside_radius(s, 3) - - for n = 1, #objs do - - if objs[n]:is_player() then - lp = objs[n]:get_pos() - break - end - end - - -- look at any players nearby, otherwise turn randomly - if lp then - - local vec = { - x = lp.x - s.x, - z = lp.z - s.z - } - - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - if lp.x > s.x then yaw = yaw + math_pi end - else - yaw = yaw + math_random(-0.5, 0.5) - end - - yaw = set_yaw(self, yaw, 8) - end - - set_velocity(self, 0) - set_animation(self, "stand") - - -- npc's ordered to stand stay standing - if self.type ~= "npc" - or self.order ~= "stand" then - - if self.walk_chance ~= 0 - and self.facing_fence ~= true - and math_random(1, 100) <= self.walk_chance - and is_at_cliff_or_danger(self) == false then - - set_velocity(self, self.walk_velocity) - self.state = "walk" - set_animation(self, "walk") - end - end - - elseif self.state == "walk" then - - local s = self.object:get_pos() - local lp = nil - - -- is there something I need to avoid? - if (self.water_damage > 0 - and self.lava_damage > 0) - or self.breath_max ~= -1 then - - lp = minetest_find_node_near(s, 1, {"group:water", "group:lava"}) - - 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:lava"}) - - elseif self.fire_damage > 0 then - - lp = minetest_find_node_near(s, 1, {"group:fire"}) - - end - - local is_in_danger = false - if lp then - -- If mob in or on dangerous block, look for land - if (is_node_dangerous(self, self.standing_in) or - is_node_dangerous(self, self.standing_on)) or (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) and (not self.fly) then - is_in_danger = true - - -- If mob in or on dangerous block, look for land - if is_in_danger then - -- Better way to find shore - copied from upstream - lp = minetest_find_nodes_in_area_under_air( - {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, - {x = s.x + 5, y = s.y + 1, z = s.z + 5}, - {"group:solid"}) - - lp = #lp > 0 and lp[math_random(#lp)] - - -- did we find land? - if lp then - - local vec = { - x = lp.x - s.x, - z = lp.z - s.z - } - - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - - if lp.x > s.x then yaw = yaw + math_pi end - - -- look towards land and move in that direction - yaw = set_yaw(self, yaw, 6) - set_velocity(self, self.walk_velocity) - - end - end - - -- A danger is near but mob is not inside - else - - -- Randomly turn - if math_random(1, 100) <= 30 then - yaw = yaw + math_random(-0.5, 0.5) - yaw = set_yaw(self, yaw, 8) - end - end - - yaw = set_yaw(self, yaw, 8) - - -- otherwise randomly turn - elseif math_random(1, 100) <= 30 then - - yaw = yaw + math_random(-0.5, 0.5) - yaw = set_yaw(self, yaw, 8) - end - - -- stand for great fall or danger or fence in front - local cliff_or_danger = false - if is_in_danger then - cliff_or_danger = is_at_cliff_or_danger(self) - end - if self.facing_fence == true - or cliff_or_danger - or math_random(1, 100) <= 30 then - - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - else - - set_velocity(self, self.walk_velocity) - - if flight_check(self) - and self.animation - and self.animation.fly_start - and self.animation.fly_end then - set_animation(self, "fly") - else - set_animation(self, "walk") - end - end - - -- runaway when punched - elseif self.state == "runaway" then - - self.runaway_timer = self.runaway_timer + 1 - - -- stop after 5 seconds or when at cliff - if self.runaway_timer > 5 - or is_at_cliff_or_danger(self) then - self.runaway_timer = 0 - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - else - set_velocity(self, self.run_velocity) - set_animation(self, "run") - end - - -- attack routines (explode, dogfight, shoot, dogshoot) - elseif self.state == "attack" then - - local s = self.object:get_pos() - local p = self.attack:get_pos() or s - - -- stop attacking if player invisible or out of range - if not self.attack - or not self.attack:get_pos() - or not object_in_range(self, self.attack) - or self.attack:get_hp() <= 0 - or (self.attack:is_player() and mobs.invis[ self.attack:get_player_name() ]) then - - self.state = "stand" - set_velocity(self, 0) - set_animation(self, "stand") - self.attack = nil - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.path.way = nil - - return - end - - -- calculate distance from mob and enemy - local dist = vector.distance(p, s) - - if self.attack_type == "explode" then - - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + math_pi end - - yaw = set_yaw(self, yaw, 0, dtime) - - local node_break_radius = self.explosion_radius or 1 - local entity_damage_radius = self.explosion_damage_radius - or (node_break_radius * 2) - - -- start timer when in reach and line of sight - if not self.v_start - and dist <= self.reach - and line_of_sight(self, s, p, 2) then - - self.v_start = true - self.timer = 0 - self.blinktimer = 0 - mob_sound(self, "fuse", nil, false) - - -- stop timer if out of reach or direct line of sight - elseif self.allow_fuse_reset - and self.v_start - and (dist >= self.explosiontimer_reset_radius - or not line_of_sight(self, s, p, 2)) then - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.blinkstatus = false - remove_texture_mod(self, "^[brighten") - end - - -- walk right up to player unless the timer is active - if self.v_start and (self.stop_to_explode or dist < self.reach) then - set_velocity(self, 0) - else - set_velocity(self, self.run_velocity) - end - - if self.animation and self.animation.run_start then - set_animation(self, "run") - else - set_animation(self, "walk") - end - - if self.v_start then - - self.timer = self.timer + dtime - self.blinktimer = (self.blinktimer or 0) + dtime - - if self.blinktimer > 0.2 then - - self.blinktimer = 0 - - if self.blinkstatus then - remove_texture_mod(self, "^[brighten") - else - add_texture_mod(self, "^[brighten") - end - - self.blinkstatus = not self.blinkstatus - end - - if self.timer > self.explosion_timer then - - local pos = self.object:get_pos() - - if mod_explosions then - if mobs_griefing and not minetest_is_protected(pos, "") then - mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object) - else - minetest_sound_play(self.sounds.explode, { - pos = pos, - gain = 1.0, - max_hear_distance = self.sounds.distance or 32 - }, true) - - entity_physics(pos, entity_damage_radius) - effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0) - end - end - mcl_burning.extinguish(self.object) - self.object:remove() - - return true - end - end - - elseif self.attack_type == "dogfight" - or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 2) - or (self.attack_type == "dogshoot" and dist <= self.reach and dogswitch(self) == 0) then - - if self.fly - and dist > self.reach then - - local p1 = s - local me_y = math_floor(p1.y) - local p2 = p - local p_y = math_floor(p2.y + 1) - local v = self.object:get_velocity() - - if flight_check(self, s) then - - if me_y < p_y then - - self.object:set_velocity({ - x = v.x, - y = 1 * self.walk_velocity, - z = v.z - }) - - elseif me_y > p_y then - - self.object:set_velocity({ - x = v.x, - y = -1 * self.walk_velocity, - z = v.z - }) - end - else - if me_y < p_y then - - self.object:set_velocity({ - x = v.x, - y = 0.01, - z = v.z - }) - - elseif me_y > p_y then - - self.object:set_velocity({ - x = v.x, - y = -0.01, - z = v.z - }) - end - end - - end - - -- rnd: new movement direction - if self.path.following - and self.path.way - and self.attack_type ~= "dogshoot" then - - -- no paths longer than 50 - if #self.path.way > 50 - or dist < self.reach then - self.path.following = false - return - end - - local p1 = self.path.way[1] - - if not p1 then - self.path.following = false - return - end - - if math_abs(p1.x-s.x) + math_abs(p1.z - s.z) < 0.6 then - -- reached waypoint, remove it from queue - table.remove(self.path.way, 1) - end - - -- set new temporary target - p = {x = p1.x, y = p1.y, z = p1.z} - end - - local vec = { - x = p.x - s.x, - z = p.z - s.z - } - - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + math_pi end - - yaw = set_yaw(self, yaw, 0, dtime) - - -- move towards enemy if beyond mob reach - if dist > self.reach then - - -- path finding by rnd - if self.pathfinding -- only if mob has pathfinding enabled - and enable_pathfinding then - - smart_mobs(self, s, p, dist, dtime) - end - - if is_at_cliff_or_danger(self) then - - set_velocity(self, 0) - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - else - - if self.path.stuck then - set_velocity(self, self.walk_velocity) - else - set_velocity(self, self.run_velocity) - end - - if self.animation and self.animation.run_start then - set_animation(self, "run") - else - set_animation(self, "walk") - end - end - - else -- rnd: if inside reach range - - self.path.stuck = false - self.path.stuck_timer = 0 - self.path.following = false -- not stuck anymore - - set_velocity(self, 0) - - if not self.custom_attack then - - if self.timer > 1 then - - self.timer = 0 - - if self.double_melee_attack - and math_random(1, 2) == 1 then - set_animation(self, "punch2") - else - set_animation(self, "punch") - end - - local p2 = p - local s2 = s - - p2.y = p2.y + .5 - s2.y = s2.y + .5 - - if line_of_sight(self, p2, s2) == true then - - -- play attack sound - mob_sound(self, "attack") - - -- punch player (or what player is attached to) - local attached = self.attack:get_attach() - if attached then - self.attack = attached - end - self.attack:punch(self.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = self.damage} - }, nil) - end - end - else -- call custom attack every second - if self.custom_attack - and self.timer > 1 then - - self.timer = 0 - - self.custom_attack(self, p) - end - end - end - - elseif self.attack_type == "shoot" - or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 1) - or (self.attack_type == "dogshoot" and dist > self.reach and dogswitch(self) == 0) then - - p.y = p.y - .5 - s.y = s.y + .5 - - local dist = vector.distance(p, s) - local vec = { - x = p.x - s.x, - y = p.y - s.y, - z = p.z - s.z - } - - yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate - - if p.x > s.x then yaw = yaw + math_pi end - - yaw = set_yaw(self, yaw, 0, dtime) - - set_velocity(self, 0) - - local p = self.object:get_pos() - p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2 - - if self.shoot_interval - and self.timer > self.shoot_interval - and not minetest_raycast(p, self.attack:get_pos(), false, false):next() - and math_random(1, 100) <= 60 then - - self.timer = 0 - set_animation(self, "shoot") - - -- play shoot attack sound - mob_sound(self, "shoot_attack") - - -- Shoot arrow - if minetest_registered_entities[self.arrow] then - - local arrow, ent - local v = 1 - if not self.shoot_arrow then - self.firing = true - minetest_after(1, function() - self.firing = false - end) - arrow = minetest_add_entity(p, self.arrow) - ent = arrow:get_luaentity() - if ent.velocity then - v = ent.velocity - end - ent.switch = 1 - ent.owner_id = tostring(self.object) -- add unique owner id to arrow - end - - local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 - -- offset makes shoot aim accurate - vec.y = vec.y + self.shoot_offset - vec.x = vec.x * (v / amount) - vec.y = vec.y * (v / amount) - vec.z = vec.z * (v / amount) - if self.shoot_arrow then - vec = vector.normalize(vec) - self:shoot_arrow(p, vec) - else - arrow:set_velocity(vec) - end - end - end - end - end - ]]-- end diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/backup_code_api.lua index 85cf0db5f0..88b6eb0414 100644 --- a/mods/ENTITIES/mcl_mobs/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/backup_code_api.lua @@ -2593,4 +2593,559 @@ local mob_detach_child = function(self, child) self.driver = nil end -end \ No newline at end of file +end + + --[[ + + if self.state == "stand" then + + if math_random(1, 4) == 1 then + + local lp = nil + local s = self.object:get_pos() + local objs = minetest_get_objects_inside_radius(s, 3) + + for n = 1, #objs do + + if objs[n]:is_player() then + lp = objs[n]:get_pos() + break + end + end + + -- look at any players nearby, otherwise turn randomly + if lp then + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + + if lp.x > s.x then yaw = yaw + math_pi end + else + yaw = yaw + math_random(-0.5, 0.5) + end + + yaw = set_yaw(self, yaw, 8) + end + + set_velocity(self, 0) + set_animation(self, "stand") + + -- npc's ordered to stand stay standing + if self.type ~= "npc" + or self.order ~= "stand" then + + if self.walk_chance ~= 0 + and self.facing_fence ~= true + and math_random(1, 100) <= self.walk_chance + and is_at_cliff_or_danger(self) == false then + + set_velocity(self, self.walk_velocity) + self.state = "walk" + set_animation(self, "walk") + end + end + + elseif self.state == "walk" then + + local s = self.object:get_pos() + local lp = nil + + -- is there something I need to avoid? + if (self.water_damage > 0 + and self.lava_damage > 0) + or self.breath_max ~= -1 then + + lp = minetest_find_node_near(s, 1, {"group:water", "group:lava"}) + + 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:lava"}) + + elseif self.fire_damage > 0 then + + lp = minetest_find_node_near(s, 1, {"group:fire"}) + + end + + local is_in_danger = false + if lp then + -- If mob in or on dangerous block, look for land + if (is_node_dangerous(self, self.standing_in) or + is_node_dangerous(self, self.standing_on)) or (is_node_waterhazard(self, self.standing_in) or is_node_waterhazard(self, self.standing_on)) and (not self.fly) then + is_in_danger = true + + -- If mob in or on dangerous block, look for land + if is_in_danger then + -- Better way to find shore - copied from upstream + lp = minetest_find_nodes_in_area_under_air( + {x = s.x - 5, y = s.y - 0.5, z = s.z - 5}, + {x = s.x + 5, y = s.y + 1, z = s.z + 5}, + {"group:solid"}) + + lp = #lp > 0 and lp[math_random(#lp)] + + -- did we find land? + if lp then + + local vec = { + x = lp.x - s.x, + z = lp.z - s.z + } + + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + + + if lp.x > s.x then yaw = yaw + math_pi end + + -- look towards land and move in that direction + yaw = set_yaw(self, yaw, 6) + set_velocity(self, self.walk_velocity) + + end + end + + -- A danger is near but mob is not inside + else + + -- Randomly turn + if math_random(1, 100) <= 30 then + yaw = yaw + math_random(-0.5, 0.5) + yaw = set_yaw(self, yaw, 8) + end + end + + yaw = set_yaw(self, yaw, 8) + + -- otherwise randomly turn + elseif math_random(1, 100) <= 30 then + + yaw = yaw + math_random(-0.5, 0.5) + yaw = set_yaw(self, yaw, 8) + end + + -- stand for great fall or danger or fence in front + local cliff_or_danger = false + if is_in_danger then + cliff_or_danger = is_at_cliff_or_danger(self) + end + if self.facing_fence == true + or cliff_or_danger + or math_random(1, 100) <= 30 then + + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + local yaw = self.object:get_yaw() or 0 + yaw = set_yaw(self, yaw + 0.78, 8) + else + + set_velocity(self, self.walk_velocity) + + if flight_check(self) + and self.animation + and self.animation.fly_start + and self.animation.fly_end then + set_animation(self, "fly") + else + set_animation(self, "walk") + end + end + + -- runaway when punched + elseif self.state == "runaway" then + + self.runaway_timer = self.runaway_timer + 1 + + -- stop after 5 seconds or when at cliff + if self.runaway_timer > 5 + or is_at_cliff_or_danger(self) then + self.runaway_timer = 0 + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + local yaw = self.object:get_yaw() or 0 + yaw = set_yaw(self, yaw + 0.78, 8) + else + set_velocity(self, self.run_velocity) + set_animation(self, "run") + end + + -- attack routines (explode, dogfight, shoot, dogshoot) + elseif self.state == "attack" then + + local s = self.object:get_pos() + local p = self.attack:get_pos() or s + + -- stop attacking if player invisible or out of range + if not self.attack + or not self.attack:get_pos() + or not object_in_range(self, self.attack) + or self.attack:get_hp() <= 0 + or (self.attack:is_player() and mobs.invis[ self.attack:get_player_name() ]) then + + self.state = "stand" + set_velocity(self, 0) + set_animation(self, "stand") + self.attack = nil + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.path.way = nil + + return + end + + -- calculate distance from mob and enemy + local dist = vector.distance(p, s) + + if self.attack_type == "explode" then + + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + math_pi end + + yaw = set_yaw(self, yaw, 0, dtime) + + local node_break_radius = self.explosion_radius or 1 + local entity_damage_radius = self.explosion_damage_radius + or (node_break_radius * 2) + + -- start timer when in reach and line of sight + if not self.v_start + and dist <= self.reach + and line_of_sight(self, s, p, 2) then + + self.v_start = true + self.timer = 0 + self.blinktimer = 0 + mob_sound(self, "fuse", nil, false) + + -- stop timer if out of reach or direct line of sight + elseif self.allow_fuse_reset + and self.v_start + and (dist >= self.explosiontimer_reset_radius + or not line_of_sight(self, s, p, 2)) then + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.blinkstatus = false + remove_texture_mod(self, "^[brighten") + end + + -- walk right up to player unless the timer is active + if self.v_start and (self.stop_to_explode or dist < self.reach) then + set_velocity(self, 0) + else + set_velocity(self, self.run_velocity) + end + + if self.animation and self.animation.run_start then + set_animation(self, "run") + else + set_animation(self, "walk") + end + + if self.v_start then + + self.timer = self.timer + dtime + self.blinktimer = (self.blinktimer or 0) + dtime + + if self.blinktimer > 0.2 then + + self.blinktimer = 0 + + if self.blinkstatus then + remove_texture_mod(self, "^[brighten") + else + add_texture_mod(self, "^[brighten") + end + + self.blinkstatus = not self.blinkstatus + end + + if self.timer > self.explosion_timer then + + local pos = self.object:get_pos() + + if mod_explosions then + if mobs_griefing and not minetest_is_protected(pos, "") then + mcl_explosions.explode(mcl_util.get_object_center(self.object), self.explosion_strength, { drop_chance = 1.0 }, self.object) + else + minetest_sound_play(self.sounds.explode, { + pos = pos, + gain = 1.0, + max_hear_distance = self.sounds.distance or 32 + }, true) + + entity_physics(pos, entity_damage_radius) + effect(pos, 32, "mcl_particles_smoke.png", nil, nil, node_break_radius, 1, 0) + end + end + mcl_burning.extinguish(self.object) + self.object:remove() + + return true + end + end + + elseif self.attack_type == "dogfight" + or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 2) + or (self.attack_type == "dogshoot" and dist <= self.reach and dogswitch(self) == 0) then + + if self.fly + and dist > self.reach then + + local p1 = s + local me_y = math_floor(p1.y) + local p2 = p + local p_y = math_floor(p2.y + 1) + local v = self.object:get_velocity() + + if flight_check(self, s) then + + if me_y < p_y then + + self.object:set_velocity({ + x = v.x, + y = 1 * self.walk_velocity, + z = v.z + }) + + elseif me_y > p_y then + + self.object:set_velocity({ + x = v.x, + y = -1 * self.walk_velocity, + z = v.z + }) + end + else + if me_y < p_y then + + self.object:set_velocity({ + x = v.x, + y = 0.01, + z = v.z + }) + + elseif me_y > p_y then + + self.object:set_velocity({ + x = v.x, + y = -0.01, + z = v.z + }) + end + end + + end + + -- rnd: new movement direction + if self.path.following + and self.path.way + and self.attack_type ~= "dogshoot" then + + -- no paths longer than 50 + if #self.path.way > 50 + or dist < self.reach then + self.path.following = false + return + end + + local p1 = self.path.way[1] + + if not p1 then + self.path.following = false + return + end + + if math_abs(p1.x-s.x) + math_abs(p1.z - s.z) < 0.6 then + -- reached waypoint, remove it from queue + table.remove(self.path.way, 1) + end + + -- set new temporary target + p = {x = p1.x, y = p1.y, z = p1.z} + end + + local vec = { + x = p.x - s.x, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + math_pi end + + yaw = set_yaw(self, yaw, 0, dtime) + + -- move towards enemy if beyond mob reach + if dist > self.reach then + + -- path finding by rnd + if self.pathfinding -- only if mob has pathfinding enabled + and enable_pathfinding then + + smart_mobs(self, s, p, dist, dtime) + end + + if is_at_cliff_or_danger(self) then + + set_velocity(self, 0) + set_animation(self, "stand") + local yaw = self.object:get_yaw() or 0 + yaw = set_yaw(self, yaw + 0.78, 8) + else + + if self.path.stuck then + set_velocity(self, self.walk_velocity) + else + set_velocity(self, self.run_velocity) + end + + if self.animation and self.animation.run_start then + set_animation(self, "run") + else + set_animation(self, "walk") + end + end + + else -- rnd: if inside reach range + + self.path.stuck = false + self.path.stuck_timer = 0 + self.path.following = false -- not stuck anymore + + set_velocity(self, 0) + + if not self.custom_attack then + + if self.timer > 1 then + + self.timer = 0 + + if self.double_melee_attack + and math_random(1, 2) == 1 then + set_animation(self, "punch2") + else + set_animation(self, "punch") + end + + local p2 = p + local s2 = s + + p2.y = p2.y + .5 + s2.y = s2.y + .5 + + if line_of_sight(self, p2, s2) == true then + + -- play attack sound + mob_sound(self, "attack") + + -- punch player (or what player is attached to) + local attached = self.attack:get_attach() + if attached then + self.attack = attached + end + self.attack:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = self.damage} + }, nil) + end + end + else -- call custom attack every second + if self.custom_attack + and self.timer > 1 then + + self.timer = 0 + + self.custom_attack(self, p) + end + end + end + + elseif self.attack_type == "shoot" + or (self.attack_type == "dogshoot" and dogswitch(self, dtime) == 1) + or (self.attack_type == "dogshoot" and dist > self.reach and dogswitch(self) == 0) then + + p.y = p.y - .5 + s.y = s.y + .5 + + local dist = vector.distance(p, s) + local vec = { + x = p.x - s.x, + y = p.y - s.y, + z = p.z - s.z + } + + yaw = (atan(vec.z / vec.x) + math_pi / 2) - self.rotate + + if p.x > s.x then yaw = yaw + math_pi end + + yaw = set_yaw(self, yaw, 0, dtime) + + set_velocity(self, 0) + + local p = self.object:get_pos() + p.y = p.y + (self.collisionbox[2] + self.collisionbox[5]) / 2 + + if self.shoot_interval + and self.timer > self.shoot_interval + and not minetest_raycast(p, self.attack:get_pos(), false, false):next() + and math_random(1, 100) <= 60 then + + self.timer = 0 + set_animation(self, "shoot") + + -- play shoot attack sound + mob_sound(self, "shoot_attack") + + -- Shoot arrow + if minetest_registered_entities[self.arrow] then + + local arrow, ent + local v = 1 + if not self.shoot_arrow then + self.firing = true + minetest_after(1, function() + self.firing = false + end) + arrow = minetest_add_entity(p, self.arrow) + ent = arrow:get_luaentity() + if ent.velocity then + v = ent.velocity + end + ent.switch = 1 + ent.owner_id = tostring(self.object) -- add unique owner id to arrow + end + + local amount = (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) ^ 0.5 + -- offset makes shoot aim accurate + vec.y = vec.y + self.shoot_offset + vec.x = vec.x * (v / amount) + vec.y = vec.y * (v / amount) + vec.z = vec.z * (v / amount) + if self.shoot_arrow then + vec = vector.normalize(vec) + self:shoot_arrow(p, vec) + else + arrow:set_velocity(vec) + end + end + end + end + end + ]]-- \ No newline at end of file From ed6026671381c99723eccbf2089d99748e19bfe2 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 19:17:48 -0400 Subject: [PATCH 015/117] Gut even more elements of the api --- mods/ENTITIES/mcl_mobs/api.lua | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 6cc81aeb83..fff3125911 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -604,14 +604,15 @@ end local mob_step = function(self, dtime) + --do not continue if non-existent if not self or not self.object or not self.object:get_luaentity() then return false end - if self.state == "die" then - print("need custom die stop moving thing") - return - end + --if self.state == "die" then + -- print("need custom die stop moving thing") + -- return + --end -- can mob be pushed, if so calculate direction -- do this first to prevent issues if self.pushable then @@ -629,8 +630,8 @@ local mob_step = function(self, dtime) --cmi.notify_step(self.object, dtime) --end - local pos = self.object:get_pos() - local yaw = 0 + --local pos = self.object:get_pos() + --local yaw = 0 --if mobs_debug then --update_tag(self) @@ -653,6 +654,7 @@ local mob_step = function(self, dtime) -- smooth rotation by ThomasMonroe314 + --[[ if self.delay and self.delay > 0 then local yaw = self.object:get_yaw() or 0 @@ -692,6 +694,7 @@ local mob_step = function(self, dtime) self.object:set_yaw(yaw) --update_roll(self) end + ]]-- -- end rotation From 1210bc463adb949496fc521e3169fb88e49fc4e9 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 19:44:24 -0400 Subject: [PATCH 016/117] prevent mob collision detection shootout --- mods/ENTITIES/mcl_mobs/api.lua | 42 ++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index fff3125911..13bcdf6413 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -140,10 +140,18 @@ if minetest_settings:get_bool("only_peaceful_mobs", false) then end) end +local integer_test = {-1,1} +--slightly adjust mob position to prevent equal length + --corner/wall sticking + pos.x = pos.x + ((math_random()/2)*integer_test[math.random(1,2)]) + pos.z = pos.z + ((math_random()/2)*integer_test[math.random(1,2)]) + local collision = function(self) pos = self.object:get_pos() - --do collision detection from the base of the mob + + + --do collision detection from the base of the mob collisionbox = self.object:get_properties().collisionbox pos.y = pos.y + collisionbox[2] @@ -189,6 +197,7 @@ local collision = function(self) if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then dir = vector.direction(pos,pos2) + dir.y = 0 --eliminate mob being stuck in corners @@ -196,19 +205,32 @@ local collision = function(self) dir = vector.new(math_random(-1,1)*math_random(),0,math_random(-1,1)*math_random()) end - local velocity = vector.multiply(dir,1.1) + ---- JUST MAKE THIS DIR FROM NOW ON --- FIX MEEEEE + local velocity = dir--vector.multiply(dir,1.1) --local velocity = vector.normalize(dir) vel1 = vector.multiply(velocity, -1) vel2 = velocity - self.object:add_velocity(vel1) + + local current_mob_velocity = self.object:get_velocity() + + + if math.abs(current_mob_velocity.x) < 2 and math.abs(current_mob_velocity.z) < 2 then + self.object:add_velocity(vel1) + end --reenable fire spreading eventually if object:is_player() then - object:add_player_velocity(vel2) + + local current_vel = object:get_velocity() + + if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then + object:add_player_velocity(vel2) + end + --if self.on_fire then -- start_fire(object) @@ -219,7 +241,10 @@ local collision = function(self) --end else - object:add_velocity(vel2) + local current_vel = object:get_velocity() + if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then + object:add_velocity(vel2) + end --if self.on_fire then -- start_fire(object) --end @@ -381,7 +406,6 @@ end -- execute current state (stand, walk, run, attacks) -- returns true if mob has died local do_states = function(self, dtime) - local yaw = self.object:get_yaw() or 0 @@ -619,6 +643,8 @@ local mob_step = function(self, dtime) collision(self) end + do_states(self, dtime) + @@ -763,10 +789,6 @@ local mob_step = function(self, dtime) --breed(self) - --if do_states(self, dtime) then - -- return - --end - --do_jump(self) --runaway_from(self) From aa4d34c10e4bc367fc6ad7d898cd145d9f58ed0c Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 20:00:38 -0400 Subject: [PATCH 017/117] Improve mob to mob collision --- mods/ENTITIES/mcl_mobs/api.lua | 74 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 13bcdf6413..cd5379bc86 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -140,69 +140,67 @@ if minetest_settings:get_bool("only_peaceful_mobs", false) then end) end + local integer_test = {-1,1} ---slightly adjust mob position to prevent equal length - --corner/wall sticking - pos.x = pos.x + ((math_random()/2)*integer_test[math.random(1,2)]) - pos.z = pos.z + ((math_random()/2)*integer_test[math.random(1,2)]) local collision = function(self) - pos = self.object:get_pos() - - + local pos = self.object:get_pos() --do collision detection from the base of the mob - collisionbox = self.object:get_properties().collisionbox + local collisionbox = self.object:get_properties().collisionbox pos.y = pos.y + collisionbox[2] - collision_boundary = collisionbox[4] + local collision_boundary = collisionbox[4] - radius = collision_boundary + local radius = collision_boundary if collisionbox[5] > collision_boundary then radius = collisionbox[5] end - collision_count = 0 + local collision_count = 0 for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do - if object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) and + if object and object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) then--and --don't collide with rider, rider don't collide with thing - (not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and - (not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then + --(not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and + --(not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then --stop infinite loop collision_count = collision_count + 1 if collision_count > 100 then break end - pos2 = object:get_pos() + local pos2 = object:get_pos() - object_collisionbox = object:get_properties().collisionbox + local object_collisionbox = object:get_properties().collisionbox pos2.y = pos2.y + object_collisionbox[2] - object_collision_boundary = object_collisionbox[4] + local object_collision_boundary = object_collisionbox[4] --this is checking the difference of the object collided with's possision --if positive top of other object is inside (y axis) of current object - y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y + local y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y - y_top_diff = (pos.y + collisionbox[5]) - pos2.y + local y_top_diff = (pos.y + collisionbox[5]) - pos2.y - distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)) + local distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)) if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then - dir = vector.direction(pos,pos2) + local dir = vector.direction(pos,pos2) dir.y = 0 --eliminate mob being stuck in corners if dir.x == 0 and dir.z == 0 then - dir = vector.new(math_random(-1,1)*math_random(),0,math_random(-1,1)*math_random()) + --slightly adjust mob position to prevent equal length + --corner/wall sticking + dir.x = dir.x + ((math_random()/2)*integer_test[math.random(1,2)]) + dir.z = dir.z + ((math_random()/2)*integer_test[math.random(1,2)]) end ---- JUST MAKE THIS DIR FROM NOW ON --- FIX MEEEEE @@ -210,16 +208,21 @@ local collision = function(self) --local velocity = vector.normalize(dir) - vel1 = vector.multiply(velocity, -1) - vel2 = velocity + local vel1 = vector.multiply(velocity, -1) + local vel2 = velocity local current_mob_velocity = self.object:get_velocity() - if math.abs(current_mob_velocity.x) < 2 and math.abs(current_mob_velocity.z) < 2 then - self.object:add_velocity(vel1) - end + local new_mob_velocity = vector.subtract(vel1, current_mob_velocity) + + new_mob_velocity.y = 0 + + + --if math.abs(current_mob_velocity.x) < 2 and math.abs(current_mob_velocity.z) < 2 then + self.object:add_velocity(new_mob_velocity) + --end --reenable fire spreading eventually @@ -227,6 +230,12 @@ local collision = function(self) local current_vel = object:get_velocity() + + --local new_vel = vector.subtract(vel2, current_vel) + + --new_vel.y = 0 + + if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then object:add_player_velocity(vel2) end @@ -242,9 +251,14 @@ local collision = function(self) else local current_vel = object:get_velocity() - if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then - object:add_velocity(vel2) - end + + local new_vel = vector.subtract(vel2, current_vel) + + new_vel.y = 0 + + --if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then + object:add_velocity(new_vel) + --end --if self.on_fire then -- start_fire(object) --end From 3f6312a631c6726c3bc4b09d9ec3e64b3ae810e5 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 13 Apr 2021 20:24:46 -0400 Subject: [PATCH 018/117] Make mobs magnetic collision more jello-y --- mods/ENTITIES/mcl_mobs/api.lua | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index cd5379bc86..a8307be609 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -208,27 +208,31 @@ local collision = function(self) --local velocity = vector.normalize(dir) + local force = 1 - (1 * distance / (collision_boundary + object_collision_boundary)) + local vel1 = vector.multiply(velocity, -1) local vel2 = velocity - - local current_mob_velocity = self.object:get_velocity() + vel1 = vector.multiply(vel1, force) + vel2 = vector.multiply(vel2, force) - local new_mob_velocity = vector.subtract(vel1, current_mob_velocity) - new_mob_velocity.y = 0 + --local current_mob_velocity = self.object:get_velocity() + + --print(distance) + --print(collision_boundary + object_collision_boundary) --if math.abs(current_mob_velocity.x) < 2 and math.abs(current_mob_velocity.z) < 2 then - self.object:add_velocity(new_mob_velocity) + self.object:add_velocity(vel1) --end --reenable fire spreading eventually if object:is_player() then - local current_vel = object:get_velocity() + --local current_vel = object:get_velocity() --local new_vel = vector.subtract(vel2, current_vel) @@ -236,9 +240,9 @@ local collision = function(self) --new_vel.y = 0 - if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then + --if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then object:add_player_velocity(vel2) - end + --end --if self.on_fire then @@ -250,15 +254,15 @@ local collision = function(self) --end else - local current_vel = object:get_velocity() + -- local current_vel = object:get_velocity() - local new_vel = vector.subtract(vel2, current_vel) + -- local new_vel = vector.subtract(vel2, current_vel) - new_vel.y = 0 + -- new_vel.y = 0 - --if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then - object:add_velocity(new_vel) - --end + -- if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then + object:add_velocity(vel2) + -- end --if self.on_fire then -- start_fire(object) --end From 755533beeb6c708603096cce4f99bea558c8b6ce Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 14 Apr 2021 11:50:22 -0400 Subject: [PATCH 019/117] Disable literally everything in mobs api --- mods/ENTITIES/mcl_mobs/api.lua | 41 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index a8307be609..7e6f26df77 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -43,7 +43,8 @@ local math_random = math.random local math_floor = math.floor -- localize vector functions -local vector_new = vector.new +local vector_new = vector.new +local vector_length = vector.length mobs = {} -- mob constants @@ -144,6 +145,7 @@ end local integer_test = {-1,1} local collision = function(self) + --[[ local pos = self.object:get_pos() --do collision detection from the base of the mob @@ -159,6 +161,10 @@ local collision = function(self) radius = collisionbox[5] end + if self.object:get_properties().collide_with_objects == true then + print("THIS IS A SERIOUS ERROR!") + end + local collision_count = 0 for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do @@ -171,6 +177,7 @@ local collision = function(self) if collision_count > 100 then break end + local pos2 = object:get_pos() local object_collisionbox = object:get_properties().collisionbox @@ -199,8 +206,8 @@ local collision = function(self) if dir.x == 0 and dir.z == 0 then --slightly adjust mob position to prevent equal length --corner/wall sticking - dir.x = dir.x + ((math_random()/2)*integer_test[math.random(1,2)]) - dir.z = dir.z + ((math_random()/2)*integer_test[math.random(1,2)]) + dir.x = dir.x + ((math_random()/10)*integer_test[math.random(1,2)]) + dir.z = dir.z + ((math_random()/10)*integer_test[math.random(1,2)]) end ---- JUST MAKE THIS DIR FROM NOW ON --- FIX MEEEEE @@ -217,31 +224,31 @@ local collision = function(self) vel2 = vector.multiply(vel2, force) - - --local current_mob_velocity = self.object:get_velocity() + local current_mob_velocity = self.object:get_velocity() - --print(distance) - --print(collision_boundary + object_collision_boundary) - - --if math.abs(current_mob_velocity.x) < 2 and math.abs(current_mob_velocity.z) < 2 then - self.object:add_velocity(vel1) + --if vector_length(current_mob_velocity) <= 1 then + --self.object:add_velocity(vel1) --end + --reenable fire spreading eventually if object:is_player() then + print("there is something seriously wrong here") --local current_vel = object:get_velocity() + --print(vector.length(current_vel)) + --local new_vel = vector.subtract(vel2, current_vel) --new_vel.y = 0 --if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then - object:add_player_velocity(vel2) + --object:add_velocity(new_vel) --end @@ -253,15 +260,15 @@ local collision = function(self) -- start_fire(self.object) --end - else - -- local current_vel = object:get_velocity() + --else + --local current_vel = object:get_velocity() - -- local new_vel = vector.subtract(vel2, current_vel) + --local new_vel = vector.subtract(vel2, current_vel) - -- new_vel.y = 0 + --new_vel.y = 0 -- if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then - object:add_velocity(vel2) + --object:add_velocity(new_vel) -- end --if self.on_fire then -- start_fire(object) @@ -271,8 +278,10 @@ local collision = function(self) --end end end + end end + ]]-- end From d4db27f0e1edd439f65821b814146a237ebea799 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 14 Apr 2021 17:25:39 -0400 Subject: [PATCH 020/117] Update backup_code_api.lua --- mods/ENTITIES/mcl_mobs/backup_code_api.lua | 120 ++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/backup_code_api.lua index 88b6eb0414..0791d5960c 100644 --- a/mods/ENTITIES/mcl_mobs/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/backup_code_api.lua @@ -3148,4 +3148,122 @@ end end end end - ]]-- \ No newline at end of file + ]]-- + + + mobs.death_effect = function(pos, yaw, collisionbox, rotate) + local min, max + if collisionbox then + min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} + max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} + else + min = { x = -0.5, y = 0, z = -0.5 } + max = { x = 0.5, y = 0.5, z = 0.5 } + end + if rotate then + min = vector.rotate(min, {x=0, y=yaw, z=math_pi/2}) + max = vector.rotate(max, {x=0, y=yaw, z=math_pi/2}) + min, max = vector.sort(min, max) + min = vector.multiply(min, 0.5) + max = vector.multiply(max, 0.5) + end + + minetest_add_particlespawner({ + amount = 50, + time = 0.001, + minpos = vector.add(pos, min), + maxpos = vector.add(pos, max), + minvel = vector.new(-5,-5,-5), + maxvel = vector.new(5,5,5), + minexptime = 1.1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "mcl_particles_mob_death.png^[colorize:#000000:255", + }) + + minetest_sound_play("mcl_mobs_mob_poof", { + pos = pos, + gain = 1.0, + max_hear_distance = 8, + }, true) + end + +-- above function exported for mount.lua +function mobs:set_animation(self, anim) + set_animation(self, anim) +end + + +-- set defined animation +local set_animation = function(self, anim, fixed_frame) + if not self.animation or not anim then + return + end + if self.state == "die" and anim ~= "die" and anim ~= "stand" then + return + end + + self.animation.current = self.animation.current or "" + + if (anim == self.animation.current + or not self.animation[anim .. "_start"] + or not self.animation[anim .. "_end"]) and self.state ~= "die" then + return + end + + self.animation.current = anim + + local a_start = self.animation[anim .. "_start"] + local a_end + if fixed_frame then + a_end = a_start + else + a_end = self.animation[anim .. "_end"] + end + + self.object:set_animation({ + x = a_start, + y = a_end}, + self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, + 0, self.animation[anim .. "_loop"] ~= false) +end + + +-- Code to execute before custom on_rightclick handling +local on_rightclick_prefix = function(self, clicker) + local item = clicker:get_wielded_item() + + -- Name mob with nametag + if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then + + local tag = item:get_meta():get_string("name") + if tag ~= "" then + if string.len(tag) > MAX_MOB_NAME_LENGTH then + tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) + end + self.nametag = tag + + update_tag(self) + + if not mobs.is_creative(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + return true + end + + end + return false +end + +local create_mob_on_rightclick = function(on_rightclick) + return function(self, clicker) + local stop = on_rightclick_prefix(self, clicker) + if (not stop) and (on_rightclick) then + on_rightclick(self, clicker) + end + end +end \ No newline at end of file From d063db751c1657c367f2277b24a5aa51a8d90fa3 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 14 Apr 2021 17:26:20 -0400 Subject: [PATCH 021/117] Disable mcl_playerplus random check that moves players randomly --- mods/PLAYER/mcl_playerplus/init.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/PLAYER/mcl_playerplus/init.lua b/mods/PLAYER/mcl_playerplus/init.lua index de346256fa..6dbf49f7f9 100644 --- a/mods/PLAYER/mcl_playerplus/init.lua +++ b/mods/PLAYER/mcl_playerplus/init.lua @@ -158,10 +158,10 @@ minetest.register_globalstep(function(dtime) c_x, c_y = unpack(player_collision(player)) - if player:get_velocity().x + player:get_velocity().y < .5 and c_x + c_y > 0 then + --if player:get_velocity().x + player:get_velocity().y < .5 and c_x + c_y > 0 then --minetest.chat_send_player(player:get_player_name(), "pushed at " .. c_x + c_y .. " parsecs.") - player:add_velocity({x=c_x, y=0, z=c_y}) - end + --player:add_velocity({x=c_x, y=0, z=c_y}) + --end --[[ _ _ _ From 67259891a85e54f56dc543087bd98cfe12feb6f4 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 14 Apr 2021 18:01:29 -0400 Subject: [PATCH 022/117] Remove unneeded comments --- mods/ENTITIES/mcl_mobs/api.lua | 71 ++++------------------------------ 1 file changed, 8 insertions(+), 63 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 7e6f26df77..9b730d2279 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -145,7 +145,7 @@ end local integer_test = {-1,1} local collision = function(self) - --[[ + local pos = self.object:get_pos() --do collision detection from the base of the mob @@ -210,78 +210,23 @@ local collision = function(self) dir.z = dir.z + ((math_random()/10)*integer_test[math.random(1,2)]) end - ---- JUST MAKE THIS DIR FROM NOW ON --- FIX MEEEEE - local velocity = dir--vector.multiply(dir,1.1) - - --local velocity = vector.normalize(dir) + local velocity = dir - local force = 1 - (1 * distance / (collision_boundary + object_collision_boundary)) + --0.5 is the max force multiplier + local force = 0.5 - (0.5 * distance / (collision_boundary + object_collision_boundary)) - local vel1 = vector.multiply(velocity, -1) - local vel2 = velocity + local vel1 = vector.multiply(velocity, -1.5) + local vel2 = vector.multiply(velocity, 1.5) vel1 = vector.multiply(vel1, force) vel2 = vector.multiply(vel2, force) - - - local current_mob_velocity = self.object:get_velocity() - - --if vector_length(current_mob_velocity) <= 1 then - --self.object:add_velocity(vel1) - --end - - - --reenable fire spreading eventually - - if object:is_player() then - - print("there is something seriously wrong here") - --local current_vel = object:get_velocity() - - - --print(vector.length(current_vel)) - - --local new_vel = vector.subtract(vel2, current_vel) - - --new_vel.y = 0 - - - --if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then - --object:add_velocity(new_vel) - --end - - - --if self.on_fire then - -- start_fire(object) - --end - - --if is_player_on_fire(object) then - -- start_fire(self.object) - --end - - --else - --local current_vel = object:get_velocity() - - --local new_vel = vector.subtract(vel2, current_vel) - - --new_vel.y = 0 - - -- if math.abs(current_vel.x) < 2 and math.abs(current_vel.z) < 2 then - --object:add_velocity(new_vel) - -- end - --if self.on_fire then - -- start_fire(object) - --end - --if object:get_luaentity().on_fire then - -- start_fire(self.object) - --end - end + self.object:add_velocity(vel1) + object:add_velocity(vel2) end end end - ]]-- end From 8b200c7352cb9fdd01f1b073308acacd36b2672a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 14 Apr 2021 19:38:14 -0400 Subject: [PATCH 023/117] Add in basic movement rotation testing --- mods/ENTITIES/mcl_mobs/api.lua | 7 ++++++- mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 9b730d2279..152302e7d6 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -651,7 +651,6 @@ local mob_step = function(self, dtime) --end -- smooth rotation by ThomasMonroe314 - --[[ if self.delay and self.delay > 0 then @@ -1067,6 +1066,12 @@ minetest.register_entity(name, { _cmi_is_mob = true, pushable = def.pushable or true, + --j4i stuff + --automatic_rotate = 360, + automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 + automatic_face_movement_max_rotation_per_sec = 360, + backface_culling = true, + --end j4i stuff -- MCL2 extensions teleport = teleport, diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index 48fcc81975..be4cceea37 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -9,6 +9,7 @@ local cow_def = { hp_max = 10, xp_min = 1, xp_max = 3, + rotate = 270, collisionbox = {-0.45, -0.01, -0.45, 0.45, 1.39, 0.45}, visual = "mesh", mesh = "mobs_mc_cow.b3d", From 61124905f3d862d00f00674067003d8da7722405 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 09:28:22 -0400 Subject: [PATCH 024/117] Add in mob auto rotation (implementation 1) --- mods/ENTITIES/mcl_mobs/api.lua | 100 ++++++++------------- mods/ENTITIES/mcl_mobs/backup_code_api.lua | 4 +- 2 files changed, 40 insertions(+), 64 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 152302e7d6..462cb00e3c 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -233,21 +233,29 @@ end -- move mob in facing direction local set_velocity = function(self, v) - local c_x, c_y = 0, 0 + --local c_x, c_y = 0, 0 -- halt mob if it has been ordered to stay - if self.order == "stand" then - self.object:set_velocity({x = 0, y = 0, z = 0}) - return - end + --if self.order == "stand" then + --self.object:set_velocity({x = 0, y = 0, z = 0}) + -- return + --end - local yaw = (self.object:get_yaw() or 0) + self.rotate + local yaw = (self.yaw or 0) - self.object:add_velocity({ - x = (math_sin(yaw) * -v) + c_x, - y = self.object:get_velocity().y, - z = (math_cos(yaw) * v) + c_y, - }) + local current_velocity = self.object:get_velocity() + + local goal_velocity = { + x = (math_sin(yaw) * -v), + y = 0, + z = (math_cos(yaw) * v), + } + + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + + new_velocity_addition.y = 0 + + self.object:add_velocity(new_velocity_addition) end @@ -277,7 +285,7 @@ local set_yaw = function(self, yaw, delay, dtime) if self.shaking and dtime then yaw = yaw + (math_random() * 2 - 1) * 5 * dtime end - self.object:set_yaw(yaw) + self.yaw(yaw) update_roll(self) return yaw end @@ -380,7 +388,15 @@ end local do_states = function(self, dtime) local yaw = self.object:get_yaw() or 0 + self.state_timer = self.state_timer - dtime + if self.state_timer <= 0 then + self.state_timer = math.random(0,2) + math.random() + --let's do a random state + self.yaw = (math_random() * (math.pi * 2)) - math.pi + end + + set_velocity(self,1) end @@ -605,19 +621,21 @@ local mob_step = function(self, dtime) return false end + --print(self.object:get_yaw()) + --if self.state == "die" then -- print("need custom die stop moving thing") -- return --end - -- can mob be pushed, if so calculate direction -- do this first to prevent issues - if self.pushable then - collision(self) - end + do_states(self, dtime) - + -- can mob be pushed, if so calculate direction -- do this last (overrides everything) + if self.pushable then + collision(self) + end --if not self.fire_resistant then @@ -650,50 +668,6 @@ local mob_step = function(self, dtime) -- return --end - -- smooth rotation by ThomasMonroe314 - --[[ - if self.delay and self.delay > 0 then - - local yaw = self.object:get_yaw() or 0 - - if self.delay == 1 then - yaw = self.target_yaw - else - local dif = math_abs(yaw - self.target_yaw) - - if yaw > self.target_yaw then - - if dif > math_pi then - dif = 2 * math_pi - dif -- need to add - yaw = yaw + dif / self.delay - else - yaw = yaw - dif / self.delay -- need to subtract - end - - elseif yaw < self.target_yaw then - - if dif > math_pi then - dif = 2 * math_pi - dif - yaw = yaw - dif / self.delay -- need to subtract - else - yaw = yaw + dif / self.delay -- need to add - end - end - - if yaw > (math_pi * 2) then yaw = yaw - (math_pi * 2) end - if yaw < 0 then yaw = yaw + (math_pi * 2) end - end - - self.delay = self.delay - 1 - if self.shaking then - yaw = yaw + (math_random() * 2 - 1) * 5 * dtime - end - self.object:set_yaw(yaw) - --update_roll(self) - end - ]]-- - - -- end rotation -- run custom function (defined in mob lua file) --if self.do_custom then @@ -1028,6 +1002,7 @@ minetest.register_entity(name, { replace_offset = def.replace_offset or 0, on_replace = def.on_replace, timer = 0, + state_timer = 0, env_damage_timer = 0, tamed = false, pause_timer = 0, @@ -1068,8 +1043,9 @@ minetest.register_entity(name, { --j4i stuff --automatic_rotate = 360, + yaw = 0, automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 - automatic_face_movement_max_rotation_per_sec = 360, + automatic_face_movement_max_rotation_per_sec = 270, --degrees backface_culling = true, --end j4i stuff diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/backup_code_api.lua index 0791d5960c..97036fab81 100644 --- a/mods/ENTITIES/mcl_mobs/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/backup_code_api.lua @@ -2595,7 +2595,7 @@ local mob_detach_child = function(self, child) end - --[[ +function do_states(self) if self.state == "stand" then @@ -3148,7 +3148,7 @@ end end end end - ]]-- +end mobs.death_effect = function(pos, yaw, collisionbox, rotate) From ba46e7fa42bbd25175d3505ca9699a11912d491f Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 09:28:58 -0400 Subject: [PATCH 025/117] Remove old debug of colliding with objects --- mods/ENTITIES/mcl_mobs/api.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 462cb00e3c..da5dc314fa 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -161,10 +161,6 @@ local collision = function(self) radius = collisionbox[5] end - if self.object:get_properties().collide_with_objects == true then - print("THIS IS A SERIOUS ERROR!") - end - local collision_count = 0 for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do From a0ed1a0b2004baeb3d0f64c5eb02bbf0b21bf823 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 10:05:24 -0400 Subject: [PATCH 026/117] Add automatic rotation lock --- mods/ENTITIES/mcl_mobs/api.lua | 76 +++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index da5dc314fa..0517d3cffa 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -389,7 +389,7 @@ local do_states = function(self, dtime) if self.state_timer <= 0 then self.state_timer = math.random(0,2) + math.random() --let's do a random state - self.yaw = (math_random() * (math.pi * 2)) - math.pi + self.yaw = (math_random() * (math.pi * 2)) end set_velocity(self,1) @@ -610,6 +610,25 @@ local mob_activate = function(self, staticdata, def, dtime) end +--this allows auto facedir rotation while making it so mobs +--don't look like wet noodles flopping around +local movement_rotation_lock = function(self) + + local current_engine_yaw = self.object:get_yaw() + local current_lua_yaw = self.yaw + + if current_engine_yaw > math.pi * 2 then + current_engine_yaw = current_engine_yaw - (math.pi * 2) + end + + if math.abs(current_engine_yaw - current_lua_yaw) <= 0.05 and self.object:get_properties().automatic_face_movement_dir then + self.object:set_properties{automatic_face_movement_dir = false} + elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then + self.object:set_properties{automatic_face_movement_dir = self.rotate} + end +end + + local mob_step = function(self, dtime) --do not continue if non-existent @@ -625,9 +644,14 @@ local mob_step = function(self, dtime) --end + + do_states(self, dtime) + + movement_rotation_lock(self) + -- can mob be pushed, if so calculate direction -- do this last (overrides everything) if self.pushable then collision(self) @@ -947,7 +971,7 @@ minetest.register_entity(name, { spawn_small_alternative = def.spawn_small_alternative, do_custom = def.do_custom, jump_height = def.jump_height or 4, -- was 6 - rotate = math.rad(def.rotate or 0), -- 0=front, 90=side, 180=back, 270=side2 + rotate = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 lifetimer = def.lifetimer or 57.73, hp_min = scale_difficulty(def.hp_min, 5, 1), hp_max = scale_difficulty(def.hp_max, 10, 1), @@ -1108,6 +1132,54 @@ end end -- END mobs:register_mob function + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- register arrow for shoot attack function mobs:register_arrow(name, def) From 14207dd96aa60652c0ad1f4351441659c33d3ff6 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 11:23:52 -0400 Subject: [PATCH 027/117] Smooth out mob movement set_velocity more --- mods/ENTITIES/mcl_mobs/api.lua | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 0517d3cffa..4d3b2af4ad 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -229,14 +229,7 @@ end -- move mob in facing direction local set_velocity = function(self, v) - --local c_x, c_y = 0, 0 - - -- halt mob if it has been ordered to stay - --if self.order == "stand" then - --self.object:set_velocity({x = 0, y = 0, z = 0}) - -- return - --end - + local yaw = (self.yaw or 0) local current_velocity = self.object:get_velocity() @@ -247,11 +240,19 @@ local set_velocity = function(self, v) z = (math_cos(yaw) * v), } + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + if vector_length(new_velocity_addition) > vector_length(goal_velocity) then + vector.multiply(new_velocity_addition, (vector_length(goal_velocity) / vector_length(new_velocity_addition))) + end + new_velocity_addition.y = 0 - self.object:add_velocity(new_velocity_addition) + --smooths out mobs a bit + if vector_length(new_velocity_addition) >= 0.0001 then + self.object:add_velocity(new_velocity_addition) + end end @@ -620,7 +621,7 @@ local movement_rotation_lock = function(self) if current_engine_yaw > math.pi * 2 then current_engine_yaw = current_engine_yaw - (math.pi * 2) end - + if math.abs(current_engine_yaw - current_lua_yaw) <= 0.05 and self.object:get_properties().automatic_face_movement_dir then self.object:set_properties{automatic_face_movement_dir = false} elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then @@ -1204,7 +1205,7 @@ function mobs:register_arrow(name, def) rotate = def.rotate, on_punch = function(self) local vel = self.object:get_velocity() - self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) + --self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) local pos = self.object:get_pos() if self.switch == 0 From e53a193c4fe61e88e6501a2a863e22d533132ae4 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 11:25:55 -0400 Subject: [PATCH 028/117] Fix get_velocity (mobs internal) --- mods/ENTITIES/mcl_mobs/api.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 4d3b2af4ad..f02d5b4336 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -261,8 +261,11 @@ end local get_velocity = function(self) local v = self.object:get_velocity() + + v.y = 0 + if v then - return (v.x * v.x + v.z * v.z) ^ 0.5 + return vector_length(v) end return 0 From 9e4bf6e130195b4f2176658581ad17646a48ce3a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 11:29:18 -0400 Subject: [PATCH 029/117] Move old set_yaw and add node on set_velocity --- mods/ENTITIES/mcl_mobs/api.lua | 34 ++-------------------- mods/ENTITIES/mcl_mobs/backup_code_api.lua | 32 +++++++++++++++++++- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index f02d5b4336..58fee205ff 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -228,6 +228,9 @@ end -- move mob in facing direction +--this has been modified to be internal +--internal = lua (self.yaw) +--engine = c++ (self.object:get_yaw()) local set_velocity = function(self, v) local yaw = (self.yaw or 0) @@ -271,37 +274,6 @@ local get_velocity = function(self) return 0 end - --- set and return valid yaw -local set_yaw = function(self, yaw, delay, dtime) - - if not yaw or yaw ~= yaw then - yaw = 0 - end - - delay = delay or 0 - - if delay == 0 then - if self.shaking and dtime then - yaw = yaw + (math_random() * 2 - 1) * 5 * dtime - end - self.yaw(yaw) - update_roll(self) - return yaw - end - - self.target_yaw = yaw - self.delay = delay - - return self.target_yaw -end - --- global function to set mob yaw -function mobs:yaw(self, yaw, delay, dtime) - set_yaw(self, yaw, delay, dtime) -end - - -- set defined animation local set_animation = function(self, anim, fixed_frame) if not self.animation or not anim then diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/backup_code_api.lua index 97036fab81..eb1389e371 100644 --- a/mods/ENTITIES/mcl_mobs/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/backup_code_api.lua @@ -3266,4 +3266,34 @@ local create_mob_on_rightclick = function(on_rightclick) on_rightclick(self, clicker) end end -end \ No newline at end of file +end + +-- set and return valid yaw +local set_yaw = function(self, yaw, delay, dtime) + + if not yaw or yaw ~= yaw then + yaw = 0 + end + + delay = delay or 0 + + if delay == 0 then + if self.shaking and dtime then + yaw = yaw + (math_random() * 2 - 1) * 5 * dtime + end + self.yaw(yaw) + update_roll(self) + return yaw + end + + self.target_yaw = yaw + self.delay = delay + + return self.target_yaw +end + + +-- global function to set mob yaw +function mobs:yaw(self, yaw, delay, dtime) + set_yaw(self, yaw, delay, dtime) +end From bbcfb3fdb171053e3142854f658860e7693f31d1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 11:33:09 -0400 Subject: [PATCH 030/117] Randomize walking or standing on spawn in --- mods/ENTITIES/mcl_mobs/api.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api.lua index 58fee205ff..102e07c7ca 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api.lua @@ -373,6 +373,8 @@ end +local state_randomization = {"stand", "walk"} + -- get entity staticdata local mob_staticdata = function(self) @@ -394,7 +396,7 @@ local mob_staticdata = function(self) self.remove_ok = true self.attack = nil self.following = nil - self.state = "stand" + self.state = state_randomization[math.random(1,#state_randomization)] if use_cmi then self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) @@ -1043,6 +1045,8 @@ minetest.register_entity(name, { automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 automatic_face_movement_max_rotation_per_sec = 270, --degrees backface_culling = true, + walk_timer = 0, + stand_timer = 0, --end j4i stuff -- MCL2 extensions From 5155d12d05c5b563a78923b3fc02a885cd23fe85 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 14:09:54 -0400 Subject: [PATCH 031/117] Reformat mobs_mcl to api folder for ease of use --- mods/ENTITIES/mcl_mobs/{ => api}/api.lua | 1 - mods/ENTITIES/mcl_mobs/{ => api}/backup_code_api.lua | 0 mods/ENTITIES/mcl_mobs/{ => api}/mount.lua | 0 mods/ENTITIES/mcl_mobs/{ => api}/spawning.lua | 0 mods/ENTITIES/mcl_mobs/init.lua | 8 +++++--- mods/ENTITIES/mcl_mobs/lucky_block.lua | 8 -------- 6 files changed, 5 insertions(+), 12 deletions(-) rename mods/ENTITIES/mcl_mobs/{ => api}/api.lua (99%) rename mods/ENTITIES/mcl_mobs/{ => api}/backup_code_api.lua (100%) rename mods/ENTITIES/mcl_mobs/{ => api}/mount.lua (100%) rename mods/ENTITIES/mcl_mobs/{ => api}/spawning.lua (100%) delete mode 100644 mods/ENTITIES/mcl_mobs/lucky_block.lua diff --git a/mods/ENTITIES/mcl_mobs/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua similarity index 99% rename from mods/ENTITIES/mcl_mobs/api.lua rename to mods/ENTITIES/mcl_mobs/api/api.lua index 102e07c7ca..7d5bc1fd22 100644 --- a/mods/ENTITIES/mcl_mobs/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -564,7 +564,6 @@ local mob_activate = function(self, staticdata, def, dtime) -- set anything changed above self.object:set_properties(self) - set_yaw(self, (math_random(0, 360) - 180) / 180 * math_pi, 6) --update_tag(self) --set_animation(self, "stand") diff --git a/mods/ENTITIES/mcl_mobs/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/backup_code_api.lua similarity index 100% rename from mods/ENTITIES/mcl_mobs/backup_code_api.lua rename to mods/ENTITIES/mcl_mobs/api/backup_code_api.lua diff --git a/mods/ENTITIES/mcl_mobs/mount.lua b/mods/ENTITIES/mcl_mobs/api/mount.lua similarity index 100% rename from mods/ENTITIES/mcl_mobs/mount.lua rename to mods/ENTITIES/mcl_mobs/api/mount.lua diff --git a/mods/ENTITIES/mcl_mobs/spawning.lua b/mods/ENTITIES/mcl_mobs/api/spawning.lua similarity index 100% rename from mods/ENTITIES/mcl_mobs/spawning.lua rename to mods/ENTITIES/mcl_mobs/api/spawning.lua diff --git a/mods/ENTITIES/mcl_mobs/init.lua b/mods/ENTITIES/mcl_mobs/init.lua index 69246b4706..b0daba2c4b 100644 --- a/mods/ENTITIES/mcl_mobs/init.lua +++ b/mods/ENTITIES/mcl_mobs/init.lua @@ -1,14 +1,16 @@ local path = minetest.get_modpath(minetest.get_current_modname()) +local api_path = path.."/api" + -- Mob API -dofile(path .. "/api.lua") +dofile(api_path .. "/api.lua") -- Spawning Algorithm -dofile(path .. "/spawning.lua") +dofile(api_path .. "/spawning.lua") -- Rideable Mobs -dofile(path .. "/mount.lua") +dofile(api_path .. "/mount.lua") -- Mob Items dofile(path .. "/crafts.lua") \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/lucky_block.lua b/mods/ENTITIES/mcl_mobs/lucky_block.lua deleted file mode 100644 index ea90de74ac..0000000000 --- a/mods/ENTITIES/mcl_mobs/lucky_block.lua +++ /dev/null @@ -1,8 +0,0 @@ - -if minetest.get_modpath("lucky_block") then - - lucky_block:add_blocks({ - {"dro", {"mcl_mobs:nametag"}, 1}, - {"lig"}, - }) -end From 6cb6d714c9bcf55213a9449416bec37c0fe318af Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 15:04:55 -0400 Subject: [PATCH 032/117] Reorganize all mob sections into multiple files --- mods/ENTITIES/mcl_mobs/api/api.lua | 1166 +++-------------- .../mcl_mobs/api/mob_functions/ai.lua | 204 +++ .../mcl_mobs/api/mob_functions/animation.lua | 105 ++ .../{ => mob_functions}/backup_code_api.lua | 0 .../mcl_mobs/api/mob_functions/collision.lua | 84 ++ .../api/mob_functions/environment.lua | 12 + .../api/mob_functions/interaction.lua | 39 + .../mcl_mobs/api/mob_functions/movement.lua | 54 + .../mcl_mobs/api/mob_functions/set_up.lua | 215 +++ 9 files changed, 926 insertions(+), 953 deletions(-) create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua rename mods/ENTITIES/mcl_mobs/api/{ => mob_functions}/backup_code_api.lua (100%) create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 7d5bc1fd22..fad7b8c28f 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -1,8 +1,11 @@ -- API for Mobs Redo: MineClone 2 Delux 2.0 DRM Free Early Access Super Extreme Edition --- current state of things: Why? +-- current state of things: How to? --- lua locals +-- mobs library +mobs = {} + +-- lua locals - can grab from this to easily plop them into the api lua files --localize minetest functions local minetest_settings = minetest.settings @@ -46,7 +49,6 @@ local math_floor = math.floor local vector_new = vector.new local vector_length = vector.length -mobs = {} -- mob constants local MAX_MOB_NAME_LENGTH = 30 local BREED_TIME = 30 @@ -142,971 +144,229 @@ if minetest_settings:get_bool("only_peaceful_mobs", false) then end -local integer_test = {-1,1} - -local collision = function(self) - - local pos = self.object:get_pos() - - --do collision detection from the base of the mob - local collisionbox = self.object:get_properties().collisionbox - - pos.y = pos.y + collisionbox[2] - - local collision_boundary = collisionbox[4] - - local radius = collision_boundary - - if collisionbox[5] > collision_boundary then - radius = collisionbox[5] - end - - local collision_count = 0 - - for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do - if object and object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) then--and - --don't collide with rider, rider don't collide with thing - --(not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and - --(not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then - --stop infinite loop - collision_count = collision_count + 1 - if collision_count > 100 then - break - end - - local pos2 = object:get_pos() - - local object_collisionbox = object:get_properties().collisionbox - - pos2.y = pos2.y + object_collisionbox[2] - - local object_collision_boundary = object_collisionbox[4] - - - --this is checking the difference of the object collided with's possision - --if positive top of other object is inside (y axis) of current object - local y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y - - local y_top_diff = (pos.y + collisionbox[5]) - pos2.y - - - local distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)) - - if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then - - local dir = vector.direction(pos,pos2) - - dir.y = 0 - - --eliminate mob being stuck in corners - if dir.x == 0 and dir.z == 0 then - --slightly adjust mob position to prevent equal length - --corner/wall sticking - dir.x = dir.x + ((math_random()/10)*integer_test[math.random(1,2)]) - dir.z = dir.z + ((math_random()/10)*integer_test[math.random(1,2)]) - end - - local velocity = dir - - --0.5 is the max force multiplier - local force = 0.5 - (0.5 * distance / (collision_boundary + object_collision_boundary)) - - local vel1 = vector.multiply(velocity, -1.5) - local vel2 = vector.multiply(velocity, 1.5) - - vel1 = vector.multiply(vel1, force) - vel2 = vector.multiply(vel2, force) - - self.object:add_velocity(vel1) - object:add_velocity(vel2) - end - - end - end -end - - - --- move mob in facing direction ---this has been modified to be internal ---internal = lua (self.yaw) ---engine = c++ (self.object:get_yaw()) -local set_velocity = function(self, v) - - local yaw = (self.yaw or 0) - - local current_velocity = self.object:get_velocity() - - local goal_velocity = { - x = (math_sin(yaw) * -v), - y = 0, - z = (math_cos(yaw) * v), - } - - - local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) - - if vector_length(new_velocity_addition) > vector_length(goal_velocity) then - vector.multiply(new_velocity_addition, (vector_length(goal_velocity) / vector_length(new_velocity_addition))) - end - - new_velocity_addition.y = 0 - - --smooths out mobs a bit - if vector_length(new_velocity_addition) >= 0.0001 then - self.object:add_velocity(new_velocity_addition) - end -end - - - --- calculate mob velocity -local get_velocity = function(self) - - local v = self.object:get_velocity() - - v.y = 0 - - if v then - return vector_length(v) - end - - return 0 -end - --- set defined animation -local set_animation = function(self, anim, fixed_frame) - if not self.animation or not anim then - return - end - if self.state == "die" and anim ~= "die" and anim ~= "stand" then - return - end - - self.animation.current = self.animation.current or "" - - if (anim == self.animation.current - or not self.animation[anim .. "_start"] - or not self.animation[anim .. "_end"]) and self.state ~= "die" then - return - end - - self.animation.current = anim - - local a_start = self.animation[anim .. "_start"] - local a_end - if fixed_frame then - a_end = a_start - else - a_end = self.animation[anim .. "_end"] - end - - self.object:set_animation({ - x = a_start, - y = a_end}, - self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, - 0, self.animation[anim .. "_loop"] ~= false) -end - - --- above function exported for mount.lua -function mobs:set_animation(self, anim) - set_animation(self, anim) -end - -mobs.death_effect = function(pos, yaw, collisionbox, rotate) - local min, max - if collisionbox then - min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} - max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} - else - min = { x = -0.5, y = 0, z = -0.5 } - max = { x = 0.5, y = 0.5, z = 0.5 } - end - if rotate then - min = vector.rotate(min, {x=0, y=yaw, z=math_pi/2}) - max = vector.rotate(max, {x=0, y=yaw, z=math_pi/2}) - min, max = vector.sort(min, max) - min = vector.multiply(min, 0.5) - max = vector.multiply(max, 0.5) - end - - minetest_add_particlespawner({ - amount = 50, - time = 0.001, - minpos = vector.add(pos, min), - maxpos = vector.add(pos, max), - minvel = vector.new(-5,-5,-5), - maxvel = vector.new(5,5,5), - minexptime = 1.1, - maxexptime = 1.5, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "mcl_particles_mob_death.png^[colorize:#000000:255", - }) - - minetest_sound_play("mcl_mobs_mob_poof", { - pos = pos, - gain = 1.0, - max_hear_distance = 8, - }, true) -end - - --- execute current state (stand, walk, run, attacks) --- returns true if mob has died -local do_states = function(self, dtime) - local yaw = self.object:get_yaw() or 0 - - self.state_timer = self.state_timer - dtime - - if self.state_timer <= 0 then - self.state_timer = math.random(0,2) + math.random() - --let's do a random state - self.yaw = (math_random() * (math.pi * 2)) - end - - set_velocity(self,1) -end - - - -local state_randomization = {"stand", "walk"} - --- get entity staticdata -local mob_staticdata = function(self) - ---[[ - -- remove mob when out of range unless tamed - if remove_far - and self.can_despawn - and self.remove_ok - and ((not self.nametag) or (self.nametag == "")) - and self.lifetimer <= 20 then - - minetest.log("action", "Mob "..name.." despawns in mob_staticdata at "..minetest.pos_to_string(self.object.get_pos(), 1)) - mcl_burning.extinguish(self.object) - self.object:remove() - - return ""-- nil - end ---]] - self.remove_ok = true - self.attack = nil - self.following = nil - self.state = state_randomization[math.random(1,#state_randomization)] - - if use_cmi then - self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) - end - - local tmp = {} - - for _,stat in pairs(self) do - - local t = type(stat) - - if t ~= "function" - and t ~= "nil" - and t ~= "userdata" - and _ ~= "_cmi_components" then - tmp[_] = self[_] - end - end - - return minetest.serialize(tmp) -end - - --- activate mob and reload settings -local mob_activate = function(self, staticdata, def, dtime) - - -- remove monsters in peaceful mode - if self.type == "monster" - and minetest_settings:get_bool("only_peaceful_mobs", false) then - mcl_burning.extinguish(self.object) - self.object:remove() - - return - end - - -- load entity variables - local tmp = minetest.deserialize(staticdata) - - if tmp then - for _,stat in pairs(tmp) do - self[_] = stat - end - end - - -- select random texture, set model and size - if not self.base_texture then - - -- compatiblity with old simple mobs textures - if type(def.textures[1]) == "string" then - def.textures = {def.textures} - end - - self.base_texture = def.textures[math_random(1, #def.textures)] - self.base_mesh = def.mesh - self.base_size = self.visual_size - self.base_colbox = self.collisionbox - self.base_selbox = self.selectionbox - end - - -- for current mobs that dont have this set - if not self.base_selbox then - self.base_selbox = self.selectionbox or self.base_colbox - end - - -- set texture, model and size - local textures = self.base_texture - local mesh = self.base_mesh - local vis_size = self.base_size - local colbox = self.base_colbox - local selbox = self.base_selbox - - -- specific texture if gotten - if self.gotten == true - and def.gotten_texture then - textures = def.gotten_texture - end - - -- specific mesh if gotten - if self.gotten == true - and def.gotten_mesh then - mesh = def.gotten_mesh - end - - -- set child objects to half size - if self.child == true then - - vis_size = { - x = self.base_size.x * .5, - y = self.base_size.y * .5, - } - - if def.child_texture then - textures = def.child_texture[1] - end - - colbox = { - self.base_colbox[1] * .5, - self.base_colbox[2] * .5, - self.base_colbox[3] * .5, - self.base_colbox[4] * .5, - self.base_colbox[5] * .5, - self.base_colbox[6] * .5 - } - selbox = { - self.base_selbox[1] * .5, - self.base_selbox[2] * .5, - self.base_selbox[3] * .5, - self.base_selbox[4] * .5, - self.base_selbox[5] * .5, - self.base_selbox[6] * .5 - } - end - - if self.health == 0 then - self.health = math_random (self.hp_min, self.hp_max) - end - if self.breath == nil then - self.breath = self.breath_max - end - - -- pathfinding init - self.path = {} - self.path.way = {} -- path to follow, table of positions - self.path.lastpos = {x = 0, y = 0, z = 0} - self.path.stuck = false - self.path.following = false -- currently following path? - self.path.stuck_timer = 0 -- if stuck for too long search for path - - -- Armor groups - -- immortal=1 because we use custom health - -- handling (using "health" property) - local armor - if type(self.armor) == "table" then - armor = table.copy(self.armor) - armor.immortal = 1 - else - armor = {immortal=1, fleshy = self.armor} - end - self.object:set_armor_groups(armor) - self.old_y = self.object:get_pos().y - self.old_health = self.health - self.sounds.distance = self.sounds.distance or 10 - self.textures = textures - self.mesh = mesh - self.collisionbox = colbox - self.selectionbox = selbox - self.visual_size = vis_size - self.standing_in = "ignore" - self.standing_on = "ignore" - self.jump_sound_cooloff = 0 -- used to prevent jump sound from being played too often in short time - self.opinion_sound_cooloff = 0 -- used to prevent sound spam of particular sound types - - self.texture_mods = {} - self.object:set_texture_mod("") - - self.v_start = false - self.timer = 0 - self.blinktimer = 0 - self.blinkstatus = false - - -- check existing nametag - if not self.nametag then - self.nametag = def.nametag - end - - -- set anything changed above - self.object:set_properties(self) - - --update_tag(self) - --set_animation(self, "stand") - - -- run on_spawn function if found - if self.on_spawn and not self.on_spawn_run then - if self.on_spawn(self) then - self.on_spawn_run = true -- if true, set flag to run once only - end - end - - -- run after_activate - if def.after_activate then - def.after_activate(self, staticdata, def, dtime) - end - - if use_cmi then - self._cmi_components = cmi.activate_components(self.serialized_cmi_components) - cmi.notify_activate(self.object, dtime) - end -end - - ---this allows auto facedir rotation while making it so mobs ---don't look like wet noodles flopping around -local movement_rotation_lock = function(self) - - local current_engine_yaw = self.object:get_yaw() - local current_lua_yaw = self.yaw - - if current_engine_yaw > math.pi * 2 then - current_engine_yaw = current_engine_yaw - (math.pi * 2) - end - - if math.abs(current_engine_yaw - current_lua_yaw) <= 0.05 and self.object:get_properties().automatic_face_movement_dir then - self.object:set_properties{automatic_face_movement_dir = false} - elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then - self.object:set_properties{automatic_face_movement_dir = self.rotate} - end -end - - -local mob_step = function(self, dtime) - - --do not continue if non-existent - if not self or not self.object or not self.object:get_luaentity() then - return false - end - - --print(self.object:get_yaw()) - - --if self.state == "die" then - -- print("need custom die stop moving thing") - -- return - --end - - - - - - do_states(self, dtime) - - - movement_rotation_lock(self) - - -- can mob be pushed, if so calculate direction -- do this last (overrides everything) - if self.pushable then - collision(self) - end - - - --if not self.fire_resistant then - -- mcl_burning.tick(self.object, dtime) - --end - - --if use_cmi then - --cmi.notify_step(self.object, dtime) - --end - - --local pos = self.object:get_pos() - --local yaw = 0 - - --if mobs_debug then - --update_tag(self) - --end - - - - --if self.jump_sound_cooloff > 0 then - -- self.jump_sound_cooloff = self.jump_sound_cooloff - dtime - --end - - --if self.opinion_sound_cooloff > 0 then - -- self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime - --end - - --if falling(self, pos) then - -- Return if mob died after falling - -- return - --end - - - -- run custom function (defined in mob lua file) - --if self.do_custom then - - -- when false skip going any further - --if self.do_custom(self, dtime) == false then - -- return - --end - --end - - -- knockback timer - --if self.pause_timer > 0 then - - -- self.pause_timer = self.pause_timer - dtime - - -- return - --end - - -- attack timer - --self.timer = self.timer + dtime - - --[[ - if self.state ~= "attack" then - - if self.timer < 1 then - print("returning>>error code 1") - return - end - - self.timer = 0 - end - ]]-- - - -- never go over 100 - --if self.timer > 100 then - -- self.timer = 1 - --end - - -- mob plays random sound at times - --if math_random(1, 70) == 1 then - -- mob_sound(self, "random", true) - --end - - -- environmental damage timer (every 1 second) - --self.env_damage_timer = self.env_damage_timer + dtime - - --if (self.state == "attack" and self.env_damage_timer > 1) - --or self.state ~= "attack" then - -- - -- self.env_damage_timer = 0 - -- - -- -- check for environmental damage (water, fire, lava etc.) - -- if do_env_damage(self) then - -- return - -- end - -- - -- node replace check (cow eats grass etc.) - -- replace(self, pos) - --end - - --monster_attack(self) - - --npc_attack(self) - - --breed(self) - - --do_jump(self) - - --runaway_from(self) - - - --if is_at_water_danger(self) and self.state ~= "attack" then - -- if math_random(1, 10) <= 6 then - -- set_velocity(self, 0) - -- self.state = "stand" - -- set_animation(self, "stand") - -- yaw = yaw + math_random(-0.5, 0.5) - -- yaw = set_yaw(self, yaw, 8) - -- end - --end - - - -- Add water flowing for mobs from mcl_item_entity - --[[ - local p, node, nn, def - p = self.object:get_pos() - node = minetest_get_node_or_nil(p) - if node then - nn = node.name - def = minetest_registered_nodes[nnenable_physicss if not on/in flowing liquid - self._flowing = false - enable_physics(self.object, self, true) - return - end - - --Mob following code. - follow_flop(self) - - - if is_at_cliff_or_danger(self) then - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - end - - -- Despawning: when lifetimer expires, remove mob - if remove_far - and self.can_despawn == true - and ((not self.nametag) or (self.nametag == "")) - and self.state ~= "attack" - and self.following == nil then - - self.lifetimer = self.lifetimer - dtime - if self.despawn_immediately or self.lifetimer <= 0 then - minetest.log("action", "Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1)) - mcl_burning.extinguish(self.object) - self.object:remove() - elseif self.lifetimer <= 10 then - if math_random(10) < 4 then - self.despawn_immediately = true - else - self.lifetimer = 20 - end - end - end - ]]-- -end - - --- default function when mobs are blown up with TNT -local do_tnt = function(obj, damage) - - obj.object:punch(obj.object, 1.0, { - full_punch_interval = 1.0, - damage_groups = {fleshy = damage}, - }, nil) - - return false, true, {} -end +local api_path = minetest.get_modpath(minetest.get_current_modname()).."/api/mob_functions/" + +--ignite all parts of the api +dofile(api_path .. "ai.lua") +dofile(api_path .. "animation.lua") +dofile(api_path .. "collision.lua") +dofile(api_path .. "environment.lua") +dofile(api_path .. "interaction.lua") +dofile(api_path .. "movement.lua") +dofile(api_path .. "set_up.lua") mobs.spawning_mobs = {} --- Code to execute before custom on_rightclick handling -local on_rightclick_prefix = function(self, clicker) - local item = clicker:get_wielded_item() - -- Name mob with nametag - if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then - local tag = item:get_meta():get_string("name") - if tag ~= "" then - if string.len(tag) > MAX_MOB_NAME_LENGTH then - tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) - end - self.nametag = tag - - update_tag(self) - - if not mobs.is_creative(clicker:get_player_name()) then - item:take_item() - clicker:set_wielded_item(item) - end - return true - end - - end - return false -end - -local create_mob_on_rightclick = function(on_rightclick) - return function(self, clicker) - local stop = on_rightclick_prefix(self, clicker) - if (not stop) and (on_rightclick) then - on_rightclick(self, clicker) - end - end -end -- register mob entity function mobs:register_mob(name, def) + local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25} + + -- Workaround for : + -- Increase upper Y limit to avoid mobs glitching through solid nodes. + -- FIXME: Remove workaround if it's no longer needed. + + if collisionbox[5] < 0.79 then + collisionbox[5] = 0.79 + end + mobs.spawning_mobs[name] = true -local can_despawn -if def.can_despawn ~= nil then - can_despawn = def.can_despawn -elseif def.spawn_class == "passive" then - can_despawn = false -else - can_despawn = true -end - -local function scale_difficulty(value, default, min, special) - if (not value) or (value == default) or (value == special) then - return default + local can_despawn + if def.can_despawn ~= nil then + can_despawn = def.can_despawn + elseif def.spawn_class == "passive" then + can_despawn = false else - return math_max(min, value * difficulty) + can_despawn = true end -end -local collisionbox = def.collisionbox or {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25} --- Workaround for : --- Increase upper Y limit to avoid mobs glitching through solid nodes. --- FIXME: Remove workaround if it's no longer needed. -if collisionbox[5] < 0.79 then - collisionbox[5] = 0.79 -end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -minetest.register_entity(name, { - - use_texture_alpha = def.use_texture_alpha, - stepheight = def.stepheight or 0.6, - name = name, - type = def.type, - attack_type = def.attack_type, - fly = def.fly, - fly_in = def.fly_in or {"air", "__airlike"}, - owner = def.owner or "", - order = def.order or "", - on_die = def.on_die, - spawn_small_alternative = def.spawn_small_alternative, - do_custom = def.do_custom, - jump_height = def.jump_height or 4, -- was 6 - rotate = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 - lifetimer = def.lifetimer or 57.73, - hp_min = scale_difficulty(def.hp_min, 5, 1), - hp_max = scale_difficulty(def.hp_max, 10, 1), - xp_min = def.xp_min or 0, - xp_max = def.xp_max or 0, - xp_timestamp = 0, - breath_max = def.breath_max or 15, - breathes_in_water = def.breathes_in_water or false, - physical = true, - collisionbox = collisionbox, - selectionbox = def.selectionbox or def.collisionbox, - visual = def.visual, - visual_size = def.visual_size or {x = 1, y = 1}, - mesh = def.mesh, - makes_footstep_sound = def.makes_footstep_sound or false, - view_range = def.view_range or 16, - walk_velocity = def.walk_velocity or 1, - run_velocity = def.run_velocity or 2, - damage = scale_difficulty(def.damage, 0, 0), - light_damage = def.light_damage or 0, - sunlight_damage = def.sunlight_damage or 0, - water_damage = def.water_damage or 0, - lava_damage = def.lava_damage or 8, - fire_damage = def.fire_damage or 1, - suffocation = def.suffocation or true, - fall_damage = def.fall_damage or 1, - fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2 - drops = def.drops or {}, - armor = def.armor or 100, - on_rightclick = create_mob_on_rightclick(def.on_rightclick), - arrow = def.arrow, - shoot_interval = def.shoot_interval, - sounds = def.sounds or {}, - animation = def.animation, - follow = def.follow, - jump = def.jump ~= false, - walk_chance = def.walk_chance or 50, - attacks_monsters = def.attacks_monsters or false, - group_attack = def.group_attack or false, - passive = def.passive or false, - knock_back = def.knock_back ~= false, - shoot_offset = def.shoot_offset or 0, - floats = def.floats or 1, -- floats in water by default - floats_on_lava = def.floats_on_lava or 0, - replace_rate = def.replace_rate, - replace_what = def.replace_what, - replace_with = def.replace_with, - replace_offset = def.replace_offset or 0, - on_replace = def.on_replace, - timer = 0, - state_timer = 0, - env_damage_timer = 0, - tamed = false, - pause_timer = 0, - horny = false, - hornytimer = 0, - gotten = false, - health = 0, - reach = def.reach or 3, - htimer = 0, - texture_list = def.textures, - child_texture = def.child_texture, - docile_by_day = def.docile_by_day or false, - time_of_day = 0.5, - fear_height = def.fear_height or 0, - runaway = def.runaway, - runaway_timer = 0, - pathfinding = def.pathfinding, - immune_to = def.immune_to or {}, - explosion_radius = def.explosion_radius, -- LEGACY - explosion_damage_radius = def.explosion_damage_radius, -- LEGACY - explosiontimer_reset_radius = def.explosiontimer_reset_radius, - explosion_timer = def.explosion_timer or 3, - allow_fuse_reset = def.allow_fuse_reset ~= false, - stop_to_explode = def.stop_to_explode ~= false, - custom_attack = def.custom_attack, - double_melee_attack = def.double_melee_attack, - dogshoot_switch = def.dogshoot_switch, - dogshoot_count = 0, - dogshoot_count_max = def.dogshoot_count_max or 5, - dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5), - attack_animals = def.attack_animals or false, - specific_attack = def.specific_attack, - runaway_from = def.runaway_from, - owner_loyal = def.owner_loyal, - facing_fence = false, - _cmi_is_mob = true, - pushable = def.pushable or true, - - --j4i stuff - --automatic_rotate = 360, - yaw = 0, - automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 - automatic_face_movement_max_rotation_per_sec = 270, --degrees - backface_culling = true, - walk_timer = 0, - stand_timer = 0, - --end j4i stuff - - -- MCL2 extensions - teleport = teleport, - do_teleport = def.do_teleport, - spawn_class = def.spawn_class, - ignores_nametag = def.ignores_nametag or false, - rain_damage = def.rain_damage or 0, - glow = def.glow, - can_despawn = can_despawn, - child = def.child or false, - texture_mods = {}, - shoot_arrow = def.shoot_arrow, - sounds_child = def.sounds_child, - explosion_strength = def.explosion_strength, - suffocation_timer = 0, - follow_velocity = def.follow_velocity or 2.4, - instant_death = def.instant_death or false, - fire_resistant = def.fire_resistant or false, - fire_damage_resistant = def.fire_damage_resistant or false, - ignited_by_sunlight = def.ignited_by_sunlight or false, - -- End of MCL2 extensions - - on_spawn = def.on_spawn, - - on_blast = def.on_blast or do_tnt, - - on_step = mob_step, - - do_punch = def.do_punch, - - on_punch = mob_punch, - - on_breed = def.on_breed, - - on_grown = def.on_grown, - - on_detach_child = mob_detach_child, - - on_activate = function(self, staticdata, dtime) - --this is a temporary hack so mobs stop - --glitching and acting really weird with the - --default built in engine collision detection - self.object:set_properties({ - collide_with_objects = false, - }) - self.object:set_acceleration(vector_new(0,-9.81, 0)) - return mob_activate(self, staticdata, def, dtime) - end, - - get_staticdata = function(self) - return mob_staticdata(self) - end, - - harmed_by_heal = def.harmed_by_heal, - -}) - -if minetest_get_modpath("doc_identifier") ~= nil then - doc.sub.identifier.register_object(name, "basics", "mobs") -end + local function scale_difficulty(value, default, min, special) + if (not value) or (value == default) or (value == special) then + return default + else + return math_max(min, value * difficulty) + end + end + + minetest.register_entity(name, { + + use_texture_alpha = def.use_texture_alpha, + stepheight = def.stepheight or 0.6, + name = name, + type = def.type, + attack_type = def.attack_type, + fly = def.fly, + fly_in = def.fly_in or {"air", "__airlike"}, + owner = def.owner or "", + order = def.order or "", + on_die = def.on_die, + spawn_small_alternative = def.spawn_small_alternative, + do_custom = def.do_custom, + jump_height = def.jump_height or 4, -- was 6 + rotate = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 + lifetimer = def.lifetimer or 57.73, + hp_min = scale_difficulty(def.hp_min, 5, 1), + hp_max = scale_difficulty(def.hp_max, 10, 1), + xp_min = def.xp_min or 0, + xp_max = def.xp_max or 0, + xp_timestamp = 0, + breath_max = def.breath_max or 15, + breathes_in_water = def.breathes_in_water or false, + physical = true, + collisionbox = collisionbox, + selectionbox = def.selectionbox or def.collisionbox, + visual = def.visual, + visual_size = def.visual_size or {x = 1, y = 1}, + mesh = def.mesh, + makes_footstep_sound = def.makes_footstep_sound or false, + view_range = def.view_range or 16, + walk_velocity = def.walk_velocity or 1, + run_velocity = def.run_velocity or 2, + damage = scale_difficulty(def.damage, 0, 0), + light_damage = def.light_damage or 0, + sunlight_damage = def.sunlight_damage or 0, + water_damage = def.water_damage or 0, + lava_damage = def.lava_damage or 8, + fire_damage = def.fire_damage or 1, + suffocation = def.suffocation or true, + fall_damage = def.fall_damage or 1, + fall_speed = def.fall_speed or DEFAULT_FALL_SPEED, -- must be lower than -2 + drops = def.drops or {}, + armor = def.armor or 100, + on_rightclick = mobs.create_mob_on_rightclick(def.on_rightclick), + arrow = def.arrow, + shoot_interval = def.shoot_interval, + sounds = def.sounds or {}, + animation = def.animation, + follow = def.follow, + jump = def.jump ~= false, + walk_chance = def.walk_chance or 50, + attacks_monsters = def.attacks_monsters or false, + group_attack = def.group_attack or false, + passive = def.passive or false, + knock_back = def.knock_back ~= false, + shoot_offset = def.shoot_offset or 0, + floats = def.floats or 1, -- floats in water by default + floats_on_lava = def.floats_on_lava or 0, + replace_rate = def.replace_rate, + replace_what = def.replace_what, + replace_with = def.replace_with, + replace_offset = def.replace_offset or 0, + on_replace = def.on_replace, + timer = 0, + state_timer = 0, + env_damage_timer = 0, + tamed = false, + pause_timer = 0, + horny = false, + hornytimer = 0, + gotten = false, + health = 0, + reach = def.reach or 3, + htimer = 0, + texture_list = def.textures, + child_texture = def.child_texture, + docile_by_day = def.docile_by_day or false, + time_of_day = 0.5, + fear_height = def.fear_height or 0, + runaway = def.runaway, + runaway_timer = 0, + pathfinding = def.pathfinding, + immune_to = def.immune_to or {}, + explosion_radius = def.explosion_radius, -- LEGACY + explosion_damage_radius = def.explosion_damage_radius, -- LEGACY + explosiontimer_reset_radius = def.explosiontimer_reset_radius, + explosion_timer = def.explosion_timer or 3, + allow_fuse_reset = def.allow_fuse_reset ~= false, + stop_to_explode = def.stop_to_explode ~= false, + custom_attack = def.custom_attack, + double_melee_attack = def.double_melee_attack, + dogshoot_switch = def.dogshoot_switch, + dogshoot_count = 0, + dogshoot_count_max = def.dogshoot_count_max or 5, + dogshoot_count2_max = def.dogshoot_count2_max or (def.dogshoot_count_max or 5), + attack_animals = def.attack_animals or false, + specific_attack = def.specific_attack, + runaway_from = def.runaway_from, + owner_loyal = def.owner_loyal, + facing_fence = false, + _cmi_is_mob = true, + pushable = def.pushable or true, + + --j4i stuff + --automatic_rotate = 360, + yaw = 0, + automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 + automatic_face_movement_max_rotation_per_sec = 270, --degrees + backface_culling = true, + walk_timer = 0, + stand_timer = 0, + --end j4i stuff + + -- MCL2 extensions + teleport = teleport, + do_teleport = def.do_teleport, + spawn_class = def.spawn_class, + ignores_nametag = def.ignores_nametag or false, + rain_damage = def.rain_damage or 0, + glow = def.glow, + can_despawn = can_despawn, + child = def.child or false, + texture_mods = {}, + shoot_arrow = def.shoot_arrow, + sounds_child = def.sounds_child, + explosion_strength = def.explosion_strength, + suffocation_timer = 0, + follow_velocity = def.follow_velocity or 2.4, + instant_death = def.instant_death or false, + fire_resistant = def.fire_resistant or false, + fire_damage_resistant = def.fire_damage_resistant or false, + ignited_by_sunlight = def.ignited_by_sunlight or false, + -- End of MCL2 extensions + + on_spawn = def.on_spawn, + + on_blast = def.on_blast or do_tnt, + + on_step = mobs.mob_step, + + do_punch = def.do_punch, + + on_punch = mob_punch, + + on_breed = def.on_breed, + + on_grown = def.on_grown, + + on_detach_child = mob_detach_child, + + on_activate = function(self, staticdata, dtime) + --this is a temporary hack so mobs stop + --glitching and acting really weird with the + --default built in engine collision detection + self.object:set_properties({ + collide_with_objects = false, + }) + self.object:set_acceleration(vector_new(0,-9.81, 0)) + return mobs.mob_activate(self, staticdata, def, dtime) + end, + + get_staticdata = function(self) + return mobs.mob_staticdata(self) + end, + + harmed_by_heal = def.harmed_by_heal, + + }) + + if minetest_get_modpath("doc_identifier") ~= nil then + doc.sub.identifier.register_object(name, "basics", "mobs") + end end -- END mobs:register_mob function diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua new file mode 100644 index 0000000000..1a3066b971 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -0,0 +1,204 @@ +local math_random = math.random + +-- execute current state (stand, walk, run, attacks) +-- returns true if mob has died +local do_states = function(self, dtime) + local yaw = self.object:get_yaw() or 0 + + self.state_timer = self.state_timer - dtime + + if self.state_timer <= 0 then + self.state_timer = math.random(0,2) + math.random() + --let's do a random state + self.yaw = (math_random() * (math.pi * 2)) + end + + mobs.set_velocity(self,1) +end + + +mobs.mob_step = function(self, dtime) + + --do not continue if non-existent + if not self or not self.object or not self.object:get_luaentity() then + return false + end + + --print(self.object:get_yaw()) + + --if self.state == "die" then + -- print("need custom die stop moving thing") + -- return + --end + + + do_states(self, dtime) + + + mobs.movement_rotation_lock(self) + + -- can mob be pushed, if so calculate direction -- do this last (overrides everything) + if self.pushable then + mobs.collision(self) + end + + + --if not self.fire_resistant then + -- mcl_burning.tick(self.object, dtime) + --end + + --if use_cmi then + --cmi.notify_step(self.object, dtime) + --end + + --local pos = self.object:get_pos() + --local yaw = 0 + + --if mobs_debug then + --update_tag(self) + --end + + + + --if self.jump_sound_cooloff > 0 then + -- self.jump_sound_cooloff = self.jump_sound_cooloff - dtime + --end + + --if self.opinion_sound_cooloff > 0 then + -- self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime + --end + + --if falling(self, pos) then + -- Return if mob died after falling + -- return + --end + + + -- run custom function (defined in mob lua file) + --if self.do_custom then + + -- when false skip going any further + --if self.do_custom(self, dtime) == false then + -- return + --end + --end + + -- knockback timer + --if self.pause_timer > 0 then + + -- self.pause_timer = self.pause_timer - dtime + + -- return + --end + + -- attack timer + --self.timer = self.timer + dtime + + --[[ + if self.state ~= "attack" then + + if self.timer < 1 then + print("returning>>error code 1") + return + end + + self.timer = 0 + end + ]]-- + + -- never go over 100 + --if self.timer > 100 then + -- self.timer = 1 + --end + + -- mob plays random sound at times + --if math_random(1, 70) == 1 then + -- mob_sound(self, "random", true) + --end + + -- environmental damage timer (every 1 second) + --self.env_damage_timer = self.env_damage_timer + dtime + + --if (self.state == "attack" and self.env_damage_timer > 1) + --or self.state ~= "attack" then + -- + -- self.env_damage_timer = 0 + -- + -- -- check for environmental damage (water, fire, lava etc.) + -- if do_env_damage(self) then + -- return + -- end + -- + -- node replace check (cow eats grass etc.) + -- replace(self, pos) + --end + + --monster_attack(self) + + --npc_attack(self) + + --breed(self) + + --do_jump(self) + + --runaway_from(self) + + + --if is_at_water_danger(self) and self.state ~= "attack" then + -- if math_random(1, 10) <= 6 then + -- set_velocity(self, 0) + -- self.state = "stand" + -- set_animation(self, "stand") + -- yaw = yaw + math_random(-0.5, 0.5) + -- yaw = set_yaw(self, yaw, 8) + -- end + --end + + + -- Add water flowing for mobs from mcl_item_entity + --[[ + local p, node, nn, def + p = self.object:get_pos() + node = minetest_get_node_or_nil(p) + if node then + nn = node.name + def = minetest_registered_nodes[nnenable_physicss if not on/in flowing liquid + self._flowing = false + enable_physics(self.object, self, true) + return + end + + --Mob following code. + follow_flop(self) + + + if is_at_cliff_or_danger(self) then + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + local yaw = self.object:get_yaw() or 0 + yaw = set_yaw(self, yaw + 0.78, 8) + end + + -- Despawning: when lifetimer expires, remove mob + if remove_far + and self.can_despawn == true + and ((not self.nametag) or (self.nametag == "")) + and self.state ~= "attack" + and self.following == nil then + + self.lifetimer = self.lifetimer - dtime + if self.despawn_immediately or self.lifetimer <= 0 then + minetest.log("action", "Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1)) + mcl_burning.extinguish(self.object) + self.object:remove() + elseif self.lifetimer <= 10 then + if math_random(10) < 4 then + self.despawn_immediately = true + else + self.lifetimer = 20 + end + end + end + ]]-- +end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua new file mode 100644 index 0000000000..8de235ab76 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -0,0 +1,105 @@ +local math_pi = math.pi +local math_sin = math.sin +local math_cos = math.cos + +-- set defined animation +local set_animation = function(self, anim, fixed_frame) + if not self.animation or not anim then + return + end + if self.state == "die" and anim ~= "die" and anim ~= "stand" then + return + end + + self.animation.current = self.animation.current or "" + + if (anim == self.animation.current + or not self.animation[anim .. "_start"] + or not self.animation[anim .. "_end"]) and self.state ~= "die" then + return + end + + self.animation.current = anim + + local a_start = self.animation[anim .. "_start"] + local a_end + if fixed_frame then + a_end = a_start + else + a_end = self.animation[anim .. "_end"] + end + + self.object:set_animation({ + x = a_start, + y = a_end}, + self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, + 0, self.animation[anim .. "_loop"] ~= false) +end + + +-- above function exported for mount.lua +function mobs:set_animation(self, anim) + set_animation(self, anim) +end + + + + +mobs.death_effect = function(pos, yaw, collisionbox, rotate) + local min, max + if collisionbox then + min = {x=collisionbox[1], y=collisionbox[2], z=collisionbox[3]} + max = {x=collisionbox[4], y=collisionbox[5], z=collisionbox[6]} + else + min = { x = -0.5, y = 0, z = -0.5 } + max = { x = 0.5, y = 0.5, z = 0.5 } + end + if rotate then + min = vector.rotate(min, {x=0, y=yaw, z=math_pi/2}) + max = vector.rotate(max, {x=0, y=yaw, z=math_pi/2}) + min, max = vector.sort(min, max) + min = vector.multiply(min, 0.5) + max = vector.multiply(max, 0.5) + end + + minetest_add_particlespawner({ + amount = 50, + time = 0.001, + minpos = vector.add(pos, min), + maxpos = vector.add(pos, max), + minvel = vector.new(-5,-5,-5), + maxvel = vector.new(5,5,5), + minexptime = 1.1, + maxexptime = 1.5, + minsize = 1, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "mcl_particles_mob_death.png^[colorize:#000000:255", + }) + + minetest_sound_play("mcl_mobs_mob_poof", { + pos = pos, + gain = 1.0, + max_hear_distance = 8, + }, true) +end + + +--this allows auto facedir rotation while making it so mobs +--don't look like wet noodles flopping around +mobs.movement_rotation_lock = function(self) + + local current_engine_yaw = self.object:get_yaw() + local current_lua_yaw = self.yaw + + if current_engine_yaw > math.pi * 2 then + current_engine_yaw = current_engine_yaw - (math.pi * 2) + end + + if math.abs(current_engine_yaw - current_lua_yaw) <= 0.05 and self.object:get_properties().automatic_face_movement_dir then + self.object:set_properties{automatic_face_movement_dir = false} + elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then + self.object:set_properties{automatic_face_movement_dir = self.rotate} + end +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua similarity index 100% rename from mods/ENTITIES/mcl_mobs/api/backup_code_api.lua rename to mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua new file mode 100644 index 0000000000..525dcfd6a5 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -0,0 +1,84 @@ +local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius + +local integer_test = {-1,1} + +mobs.collision = function(self) + + local pos = self.object:get_pos() + + --do collision detection from the base of the mob + local collisionbox = self.object:get_properties().collisionbox + + pos.y = pos.y + collisionbox[2] + + local collision_boundary = collisionbox[4] + + local radius = collision_boundary + + if collisionbox[5] > collision_boundary then + radius = collisionbox[5] + end + + local collision_count = 0 + + for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do + if object and object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) then--and + --don't collide with rider, rider don't collide with thing + --(not object:get_attach() or (object:get_attach() and object:get_attach() ~= self.object)) and + --(not self.object:get_attach() or (self.object:get_attach() and self.object:get_attach() ~= object)) then + --stop infinite loop + collision_count = collision_count + 1 + if collision_count > 100 then + break + end + + local pos2 = object:get_pos() + + local object_collisionbox = object:get_properties().collisionbox + + pos2.y = pos2.y + object_collisionbox[2] + + local object_collision_boundary = object_collisionbox[4] + + + --this is checking the difference of the object collided with's possision + --if positive top of other object is inside (y axis) of current object + local y_base_diff = (pos2.y + object_collisionbox[5]) - pos.y + + local y_top_diff = (pos.y + collisionbox[5]) - pos2.y + + + local distance = vector.distance(vector.new(pos.x,0,pos.z),vector.new(pos2.x,0,pos2.z)) + + if distance <= collision_boundary + object_collision_boundary and y_base_diff >= 0 and y_top_diff >= 0 then + + local dir = vector.direction(pos,pos2) + + dir.y = 0 + + --eliminate mob being stuck in corners + if dir.x == 0 and dir.z == 0 then + --slightly adjust mob position to prevent equal length + --corner/wall sticking + dir.x = dir.x + ((math_random()/10)*integer_test[math.random(1,2)]) + dir.z = dir.z + ((math_random()/10)*integer_test[math.random(1,2)]) + end + + local velocity = dir + + --0.5 is the max force multiplier + local force = 0.5 - (0.5 * distance / (collision_boundary + object_collision_boundary)) + + local vel1 = vector.multiply(velocity, -1.5) + local vel2 = vector.multiply(velocity, 1.5) + + vel1 = vector.multiply(vel1, force) + vel2 = vector.multiply(vel2, force) + + self.object:add_velocity(vel1) + object:add_velocity(vel2) + end + + end + end +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua new file mode 100644 index 0000000000..082e88543f --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -0,0 +1,12 @@ +-- default function when mobs are blown up with TNT +local do_tnt = function(obj, damage) + + obj.object:punch(obj.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = damage}, + }, nil) + + return false, true, {} +end + + diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua new file mode 100644 index 0000000000..b996867cf8 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -0,0 +1,39 @@ +-- Code to execute before custom on_rightclick handling +local on_rightclick_prefix = function(self, clicker) + local item = clicker:get_wielded_item() + + -- Name mob with nametag + if not self.ignores_nametag and item:get_name() == "mcl_mobs:nametag" then + + local tag = item:get_meta():get_string("name") + if tag ~= "" then + if string.len(tag) > MAX_MOB_NAME_LENGTH then + tag = string.sub(tag, 1, MAX_MOB_NAME_LENGTH) + end + self.nametag = tag + + update_tag(self) + + if not mobs.is_creative(clicker:get_player_name()) then + item:take_item() + clicker:set_wielded_item(item) + end + return true + end + + end + return false +end + +mobs.create_mob_on_rightclick = function(on_rightclick) + return function(self, clicker) + local stop = on_rightclick_prefix(self, clicker) + if (not stop) and (on_rightclick) then + on_rightclick(self, clicker) + end + end +end + +mobs.feed_tame = function(self) + return nil +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua new file mode 100644 index 0000000000..8fb30f76a5 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -0,0 +1,54 @@ +local math_pi = math.pi +local math_sin = math.sin +local math_cos = math.cos + +-- localize vector functions +local vector_new = vector.new +local vector_length = vector.length + +-- move mob in facing direction +--this has been modified to be internal +--internal = lua (self.yaw) +--engine = c++ (self.object:get_yaw()) +mobs.set_velocity = function(self, v) + + local yaw = (self.yaw or 0) + + local current_velocity = self.object:get_velocity() + + local goal_velocity = { + x = (math_sin(yaw) * -v), + y = 0, + z = (math_cos(yaw) * v), + } + + + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + + if vector_length(new_velocity_addition) > vector_length(goal_velocity) then + vector.multiply(new_velocity_addition, (vector_length(goal_velocity) / vector_length(new_velocity_addition))) + end + + new_velocity_addition.y = 0 + + --smooths out mobs a bit + if vector_length(new_velocity_addition) >= 0.0001 then + self.object:add_velocity(new_velocity_addition) + end +end + + + +-- calculate mob velocity +mobs.get_velocity = function(self) + + local v = self.object:get_velocity() + + v.y = 0 + + if v then + return vector_length(v) + end + + return 0 +end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua new file mode 100644 index 0000000000..87e1fb8df1 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -0,0 +1,215 @@ +local math_random = math.random + + +local state_randomization = {"stand", "walk"} + +-- get entity staticdata +mobs.mob_staticdata = function(self) + +--[[ + -- remove mob when out of range unless tamed + if remove_far + and self.can_despawn + and self.remove_ok + and ((not self.nametag) or (self.nametag == "")) + and self.lifetimer <= 20 then + + minetest.log("action", "Mob "..name.." despawns in mob_staticdata at "..minetest.pos_to_string(self.object.get_pos(), 1)) + mcl_burning.extinguish(self.object) + self.object:remove() + + return ""-- nil + end +--]] + self.remove_ok = true + self.attack = nil + self.following = nil + self.state = state_randomization[math.random(1,#state_randomization)] + + if use_cmi then + self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) + end + + local tmp = {} + + for _,stat in pairs(self) do + + local t = type(stat) + + if t ~= "function" + and t ~= "nil" + and t ~= "userdata" + and _ ~= "_cmi_components" then + tmp[_] = self[_] + end + end + + return minetest.serialize(tmp) +end + + +-- activate mob and reload settings +mobs.mob_activate = function(self, staticdata, def, dtime) + + -- remove monsters in peaceful mode + if self.type == "monster" + and minetest_settings:get_bool("only_peaceful_mobs", false) then + mcl_burning.extinguish(self.object) + self.object:remove() + + return + end + + -- load entity variables + local tmp = minetest.deserialize(staticdata) + + if tmp then + for _,stat in pairs(tmp) do + self[_] = stat + end + end + + -- select random texture, set model and size + if not self.base_texture then + + -- compatiblity with old simple mobs textures + if type(def.textures[1]) == "string" then + def.textures = {def.textures} + end + + self.base_texture = def.textures[math_random(1, #def.textures)] + self.base_mesh = def.mesh + self.base_size = self.visual_size + self.base_colbox = self.collisionbox + self.base_selbox = self.selectionbox + end + + -- for current mobs that dont have this set + if not self.base_selbox then + self.base_selbox = self.selectionbox or self.base_colbox + end + + -- set texture, model and size + local textures = self.base_texture + local mesh = self.base_mesh + local vis_size = self.base_size + local colbox = self.base_colbox + local selbox = self.base_selbox + + -- specific texture if gotten + if self.gotten == true + and def.gotten_texture then + textures = def.gotten_texture + end + + -- specific mesh if gotten + if self.gotten == true + and def.gotten_mesh then + mesh = def.gotten_mesh + end + + -- set child objects to half size + if self.child == true then + + vis_size = { + x = self.base_size.x * .5, + y = self.base_size.y * .5, + } + + if def.child_texture then + textures = def.child_texture[1] + end + + colbox = { + self.base_colbox[1] * .5, + self.base_colbox[2] * .5, + self.base_colbox[3] * .5, + self.base_colbox[4] * .5, + self.base_colbox[5] * .5, + self.base_colbox[6] * .5 + } + selbox = { + self.base_selbox[1] * .5, + self.base_selbox[2] * .5, + self.base_selbox[3] * .5, + self.base_selbox[4] * .5, + self.base_selbox[5] * .5, + self.base_selbox[6] * .5 + } + end + + if self.health == 0 then + self.health = math_random (self.hp_min, self.hp_max) + end + if self.breath == nil then + self.breath = self.breath_max + end + + -- pathfinding init + self.path = {} + self.path.way = {} -- path to follow, table of positions + self.path.lastpos = {x = 0, y = 0, z = 0} + self.path.stuck = false + self.path.following = false -- currently following path? + self.path.stuck_timer = 0 -- if stuck for too long search for path + + -- Armor groups + -- immortal=1 because we use custom health + -- handling (using "health" property) + local armor + if type(self.armor) == "table" then + armor = table.copy(self.armor) + armor.immortal = 1 + else + armor = {immortal=1, fleshy = self.armor} + end + self.object:set_armor_groups(armor) + self.old_y = self.object:get_pos().y + self.old_health = self.health + self.sounds.distance = self.sounds.distance or 10 + self.textures = textures + self.mesh = mesh + self.collisionbox = colbox + self.selectionbox = selbox + self.visual_size = vis_size + self.standing_in = "ignore" + self.standing_on = "ignore" + self.jump_sound_cooloff = 0 -- used to prevent jump sound from being played too often in short time + self.opinion_sound_cooloff = 0 -- used to prevent sound spam of particular sound types + + self.texture_mods = {} + self.object:set_texture_mod("") + + self.v_start = false + self.timer = 0 + self.blinktimer = 0 + self.blinkstatus = false + + -- check existing nametag + if not self.nametag then + self.nametag = def.nametag + end + + -- set anything changed above + self.object:set_properties(self) + + --update_tag(self) + --set_animation(self, "stand") + + -- run on_spawn function if found + if self.on_spawn and not self.on_spawn_run then + if self.on_spawn(self) then + self.on_spawn_run = true -- if true, set flag to run once only + end + end + + -- run after_activate + if def.after_activate then + def.after_activate(self, staticdata, def, dtime) + end + + if use_cmi then + self._cmi_components = cmi.activate_components(self.serialized_cmi_components) + cmi.notify_activate(self.object, dtime) + end +end \ No newline at end of file From d07d0ae31c0d39c526c8418e725b5dce1d120793 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 15:34:07 -0400 Subject: [PATCH 033/117] Make mobs jump properly --- .../mcl_mobs/api/mob_functions/ai.lua | 42 +++++++++++++++++++ .../mcl_mobs/api/mob_functions/movement.lua | 12 ++++++ 2 files changed, 54 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 1a3066b971..a1f829d848 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -1,5 +1,14 @@ local math_random = math.random +local vector_multiply = vector.multiply + +local minetest_yaw_to_dir = minetest.yaw_to_dir +local minetest_get_item_group = minetest.get_item_group +local minetest_get_node = minetest.get_node + + + + -- execute current state (stand, walk, run, attacks) -- returns true if mob has died local do_states = function(self, dtime) @@ -17,6 +26,35 @@ local do_states = function(self, dtime) end + + + + +--check if a mob needs to jump +local jump_check = function(self,dtime) + + local pos = self.object:get_pos() + pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + + vector_multiply(dir, radius) + + + local test_dir = vector.add(pos,dir) + + if minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 then + print("jump") + mobs.jump(self) + end +end + + + + + mobs.mob_step = function(self, dtime) --do not continue if non-existent @@ -34,6 +72,8 @@ mobs.mob_step = function(self, dtime) do_states(self, dtime) + jump_check(self) + mobs.movement_rotation_lock(self) @@ -201,4 +241,6 @@ mobs.mob_step = function(self, dtime) end end ]]-- + + self.old_velocity = self.object:get_velocity() end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 8fb30f76a5..72ee3824d7 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -51,4 +51,16 @@ mobs.get_velocity = function(self) end return 0 +end + +--make mobs jump +mobs.jump = function(self, velocity) + + if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then + return + end + + velocity = velocity or 5 + + self.object:add_velocity(vector_new(0,velocity,0)) end \ No newline at end of file From 246bdf9707c98f787cb5264dc7ff638e340d768b Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 15:55:10 -0400 Subject: [PATCH 034/117] Implement basic mob walking animation test --- mods/ENTITIES/mcl_mobs/api/api.lua | 3 +-- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 3 ++- .../mcl_mobs/api/mob_functions/animation.lua | 13 +++---------- mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index fad7b8c28f..9ffb4f3e42 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -299,10 +299,9 @@ function mobs:register_mob(name, def) pushable = def.pushable or true, --j4i stuff - --automatic_rotate = 360, yaw = 0, automatic_face_movement_dir = def.rotate or 0, -- 0=front, 90=side, 180=back, 270=side2 - automatic_face_movement_max_rotation_per_sec = 270, --degrees + automatic_face_movement_max_rotation_per_sec = 360, --degrees backface_culling = true, walk_timer = 0, stand_timer = 0, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index a1f829d848..2b16bfb40c 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -20,6 +20,8 @@ local do_states = function(self, dtime) self.state_timer = math.random(0,2) + math.random() --let's do a random state self.yaw = (math_random() * (math.pi * 2)) + + mobs.set_animation(self, "walk") end mobs.set_velocity(self,1) @@ -46,7 +48,6 @@ local jump_check = function(self,dtime) local test_dir = vector.add(pos,dir) if minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 then - print("jump") mobs.jump(self) end end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 8de235ab76..5750a63b8d 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -3,7 +3,7 @@ local math_sin = math.sin local math_cos = math.cos -- set defined animation -local set_animation = function(self, anim, fixed_frame) +mobs.set_animation = function(self, anim, fixed_frame) if not self.animation or not anim then return end @@ -13,9 +13,8 @@ local set_animation = function(self, anim, fixed_frame) self.animation.current = self.animation.current or "" - if (anim == self.animation.current - or not self.animation[anim .. "_start"] - or not self.animation[anim .. "_end"]) and self.state ~= "die" then + if (not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) then + print("largablarga") return end @@ -37,12 +36,6 @@ local set_animation = function(self, anim, fixed_frame) end --- above function exported for mount.lua -function mobs:set_animation(self, anim) - set_animation(self, anim) -end - - mobs.death_effect = function(pos, yaw, collisionbox, rotate) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua index 87e1fb8df1..a0f7b1def5 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -194,7 +194,7 @@ mobs.mob_activate = function(self, staticdata, def, dtime) self.object:set_properties(self) --update_tag(self) - --set_animation(self, "stand") + --mobs.set_animation(self, "stand") -- run on_spawn function if found if self.on_spawn and not self.on_spawn_run then From 375d683d08266586d024491dcba2268c66583989 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 16:18:42 -0400 Subject: [PATCH 035/117] Fix forgotten localization in collision.lua --- mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua index 525dcfd6a5..e6c89e2dbc 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -1,5 +1,7 @@ local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius +local math_random = math.random + local integer_test = {-1,1} mobs.collision = function(self) From c2bac87a6d03364193aedf67c780fdea9f545cac Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Thu, 15 Apr 2021 21:46:33 -0400 Subject: [PATCH 036/117] Update set_up.lua --- mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua index a0f7b1def5..8a17582386 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -1,5 +1,6 @@ local math_random = math.random +local minetest_settings = minetest.settings local state_randomization = {"stand", "walk"} From 626c30de6d4191cd4a18b0f11cb4805c425f9648 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 11:30:55 -0400 Subject: [PATCH 037/117] Create todo.txt --- mods/ENTITIES/mcl_mobs/todo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 mods/ENTITIES/mcl_mobs/todo.txt diff --git a/mods/ENTITIES/mcl_mobs/todo.txt b/mods/ENTITIES/mcl_mobs/todo.txt new file mode 100644 index 0000000000..7598b14ed8 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/todo.txt @@ -0,0 +1 @@ +--use vector.distance to count down mob despawn timer \ No newline at end of file From 94ca7e8b89bd39144d85bc6a622778babb226d47 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 11:31:18 -0400 Subject: [PATCH 038/117] Add in state switch and state execution for mobs --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + .../mcl_mobs/api/mob_functions/ai.lua | 42 ++++++++++++++----- .../mcl_mobs/api/mob_functions/set_up.lua | 10 +++-- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 9ffb4f3e42..50d744e6c2 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -305,6 +305,7 @@ function mobs:register_mob(name, def) backface_culling = true, walk_timer = 0, stand_timer = 0, + wandering = true, --end j4i stuff -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 2b16bfb40c..1e9143ca54 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -7,24 +7,44 @@ local minetest_get_item_group = minetest.get_item_group local minetest_get_node = minetest.get_node +local state_list_wandering = {"stand", "walk"} --- execute current state (stand, walk, run, attacks) --- returns true if mob has died -local do_states = function(self, dtime) +-- state switching logic (stand, walk, run, attacks) +local state_switch = function(self, dtime) + self.state_timer = self.state_timer - dtime + if self.wandering and self.state_timer <= 0 then + self.state_timer = math.random(4,10) + math.random() + self.state = state_list_wandering[math.random(1,#state_list_wandering)] + end +end + +-- states are executed here (goto would have been helpful :<) +local state_execution = function(self,dtime) + local yaw = self.object:get_yaw() or 0 - self.state_timer = self.state_timer - dtime + if self.state == "standing" then - if self.state_timer <= 0 then - self.state_timer = math.random(0,2) + math.random() - --let's do a random state - self.yaw = (math_random() * (math.pi * 2)) + print("stand") - mobs.set_animation(self, "walk") + elseif self.state == "walking" then + + print("walk") + + elseif self.state == "run" then + + print("run") + + elseif self.state == "attack" then + + print("attack") + end - mobs.set_velocity(self,1) + --mobs.set_animation(self, state_list_wandering[math.random(1,#state_list_wandering)]) + --mobs.set_velocity(self,1) + --self.yaw = (math_random() * (math.pi * 2)) end @@ -71,7 +91,7 @@ mobs.mob_step = function(self, dtime) --end - do_states(self, dtime) + state_switch(self, dtime) jump_check(self) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua index 8a17582386..adbb710772 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -22,6 +22,7 @@ mobs.mob_staticdata = function(self) return ""-- nil end --]] + self.remove_ok = true self.attack = nil self.following = nil @@ -53,11 +54,9 @@ end mobs.mob_activate = function(self, staticdata, def, dtime) -- remove monsters in peaceful mode - if self.type == "monster" - and minetest_settings:get_bool("only_peaceful_mobs", false) then + if self.type == "monster" and minetest_settings:get_bool("only_peaceful_mobs", false) then mcl_burning.extinguish(self.object) self.object:remove() - return end @@ -70,6 +69,11 @@ mobs.mob_activate = function(self, staticdata, def, dtime) end end + --set up wandering + if not self.wandering then + self.wandering = true + end + -- select random texture, set model and size if not self.base_texture then From a934a59f3b64e8adef64676daaf81b574a6ceecd Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 11:50:13 -0400 Subject: [PATCH 039/117] Implement mob random walk directions --- .../mcl_mobs/api/mob_functions/ai.lua | 105 +++++++++++------- 1 file changed, 62 insertions(+), 43 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 1e9143ca54..707835a6a4 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -10,46 +10,6 @@ local minetest_get_node = minetest.get_node local state_list_wandering = {"stand", "walk"} --- state switching logic (stand, walk, run, attacks) -local state_switch = function(self, dtime) - self.state_timer = self.state_timer - dtime - if self.wandering and self.state_timer <= 0 then - self.state_timer = math.random(4,10) + math.random() - self.state = state_list_wandering[math.random(1,#state_list_wandering)] - end -end - --- states are executed here (goto would have been helpful :<) -local state_execution = function(self,dtime) - - local yaw = self.object:get_yaw() or 0 - - if self.state == "standing" then - - print("stand") - - elseif self.state == "walking" then - - print("walk") - - elseif self.state == "run" then - - print("run") - - elseif self.state == "attack" then - - print("attack") - - end - - --mobs.set_animation(self, state_list_wandering[math.random(1,#state_list_wandering)]) - --mobs.set_velocity(self,1) - --self.yaw = (math_random() * (math.pi * 2)) -end - - - - --check if a mob needs to jump @@ -74,6 +34,67 @@ end +-- state switching logic (stand, walk, run, attacks) +local state_switch = function(self, dtime) + self.state_timer = self.state_timer - dtime + if self.wandering and self.state_timer <= 0 then + self.state_timer = math.random(4,10) + math.random() + self.state = state_list_wandering[math.random(1,#state_list_wandering)] + end +end + +-- states are executed here (goto would have been helpful :<) +local state_execution = function(self,dtime) + + --local yaw = self.object:get_yaw() or 0 + + if self.state == "stand" then + + print("stand") + + elseif self.state == "walk" then + + self.walk_timer = self.walk_timer - dtime + + --reset the walk timer + if self.walk_timer <= 0 then + + --re-randomize the walk timer + self.walk_timer = math.random(1,6) + math.random() + + --set the mob into a random direction + self.yaw = (math_random() * (math.pi * 2)) + end + + --do animation + mobs.set_animation(self, "walk") + + --enable rotation locking + mobs.movement_rotation_lock(self) + + --set the velocity of the mob + mobs.set_velocity(self,1) + + --check for nodes to jump over + jump_check(self) + + --print("walk") + + elseif self.state == "run" then + + print("run") + + elseif self.state == "attack" then + + print("attack") + + end + +end + + + + mobs.mob_step = function(self, dtime) @@ -93,11 +114,9 @@ mobs.mob_step = function(self, dtime) state_switch(self, dtime) - jump_check(self) + state_execution(self,dtime) - mobs.movement_rotation_lock(self) - -- can mob be pushed, if so calculate direction -- do this last (overrides everything) if self.pushable then mobs.collision(self) From f38492bcb031b7fcc2ee8299f66fcd3cd3a68398 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 11:50:29 -0400 Subject: [PATCH 040/117] Re-implement animation check gate for mobs --- mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 5750a63b8d..2dc0ce34bb 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -13,8 +13,14 @@ mobs.set_animation = function(self, anim, fixed_frame) self.animation.current = self.animation.current or "" - if (not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) then - print("largablarga") + --animations break if they are constantly set + --so we put this return gate to check if it is + --already at the animation we are trying to implement + if self.animation.current == anim then + return + end + + if (not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) then return end From 024cf46307abb6fefbfe8be04941205026561177 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 11:52:29 -0400 Subject: [PATCH 041/117] Adjust spacing in animation.lua --- mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 2dc0ce34bb..3056e59d6f 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -1,12 +1,12 @@ local math_pi = math.pi -local math_sin = math.sin -local math_cos = math.cos -- set defined animation mobs.set_animation = function(self, anim, fixed_frame) + if not self.animation or not anim then return end + if self.state == "die" and anim ~= "die" and anim ~= "stand" then return end From d0695e7929460728f7da2e01cc809cb343481e1a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 13:58:08 -0400 Subject: [PATCH 042/117] Fix mob animation "memory leak" --- mods/ENTITIES/mcl_mobs/api/api.lua | 26 ++++++++----------- .../mcl_mobs/api/mob_functions/ai.lua | 10 +++++-- .../mcl_mobs/api/mob_functions/animation.lua | 23 ++++++++-------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 50d744e6c2..e8c42b5735 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -219,6 +219,7 @@ function mobs:register_mob(name, def) breathes_in_water = def.breathes_in_water or false, physical = true, collisionbox = collisionbox, + collide_with_objects = def.collide_with_objects or false, selectionbox = def.selectionbox or def.collisionbox, visual = def.visual, visual_size = def.visual_size or {x = 1, y = 1}, @@ -306,6 +307,8 @@ function mobs:register_mob(name, def) walk_timer = 0, stand_timer = 0, wandering = true, + current_animation = "", + --set_animation = mobs.set_animation, --end j4i stuff -- MCL2 extensions @@ -331,27 +334,21 @@ function mobs:register_mob(name, def) on_spawn = def.on_spawn, - on_blast = def.on_blast or do_tnt, + --on_blast = def.on_blast or do_tnt, - on_step = mobs.mob_step, + on_step = mobs.mob_step, - do_punch = def.do_punch, + --do_punch = def.do_punch, - on_punch = mob_punch, + --on_punch = mob_punch, - on_breed = def.on_breed, + --on_breed = def.on_breed, - on_grown = def.on_grown, + --on_grown = def.on_grown, - on_detach_child = mob_detach_child, + --on_detach_child = mob_detach_child, on_activate = function(self, staticdata, dtime) - --this is a temporary hack so mobs stop - --glitching and acting really weird with the - --default built in engine collision detection - self.object:set_properties({ - collide_with_objects = false, - }) self.object:set_acceleration(vector_new(0,-9.81, 0)) return mobs.mob_activate(self, staticdata, def, dtime) end, @@ -360,8 +357,7 @@ function mobs:register_mob(name, def) return mobs.mob_staticdata(self) end, - harmed_by_heal = def.harmed_by_heal, - + --harmed_by_heal = def.harmed_by_heal, }) if minetest_get_modpath("doc_identifier") ~= nil then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 707835a6a4..11954e28a3 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -50,7 +50,13 @@ local state_execution = function(self,dtime) if self.state == "stand" then - print("stand") + --do animation + mobs.set_mob_animation(self, "stand") + + --set the velocity of the mob + mobs.set_velocity(self,0) + + --print("stand") elseif self.state == "walk" then @@ -67,7 +73,7 @@ local state_execution = function(self,dtime) end --do animation - mobs.set_animation(self, "walk") + mobs.set_mob_animation(self, "walk") --enable rotation locking mobs.movement_rotation_lock(self) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 3056e59d6f..2f89333dab 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -1,8 +1,8 @@ local math_pi = math.pi -- set defined animation -mobs.set_animation = function(self, anim, fixed_frame) - +mobs.set_mob_animation = function(self, anim, fixed_frame) + if not self.animation or not anim then return end @@ -11,23 +11,21 @@ mobs.set_animation = function(self, anim, fixed_frame) return end - self.animation.current = self.animation.current or "" - - --animations break if they are constantly set - --so we put this return gate to check if it is - --already at the animation we are trying to implement - if self.animation.current == anim then - return - end if (not self.animation[anim .. "_start"] or not self.animation[anim .. "_end"]) then return end - self.animation.current = anim + --animations break if they are constantly set + --so we put this return gate to check if it is + --already at the animation we are trying to implement + if self.current_animation == anim then + return + end local a_start = self.animation[anim .. "_start"] local a_end + if fixed_frame then a_end = a_start else @@ -39,6 +37,9 @@ mobs.set_animation = function(self, anim, fixed_frame) y = a_end}, self.animation[anim .. "_speed"] or self.animation.speed_normal or 15, 0, self.animation[anim .. "_loop"] ~= false) + + + self.current_animation = anim end From adc683c6a7cd56c33bebc22ce1363671db4f4846 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 14:19:22 -0400 Subject: [PATCH 043/117] Clear mob animation on activate --- mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua index adbb710772..1d48d52f70 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -74,6 +74,9 @@ mobs.mob_activate = function(self, staticdata, def, dtime) self.wandering = true end + --clear animation + self.current_animation = nil + -- select random texture, set model and size if not self.base_texture then From 2486ffef11113a40b43a2548bde57e9cca186da9 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 15:30:44 -0400 Subject: [PATCH 044/117] Make wandering mobs avoid cliffs --- .../mcl_mobs/api/mob_functions/ai.lua | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 11954e28a3..08d6916f57 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -1,16 +1,42 @@ local math_random = math.random local vector_multiply = vector.multiply +local vector_add = vector.add local minetest_yaw_to_dir = minetest.yaw_to_dir local minetest_get_item_group = minetest.get_item_group local minetest_get_node = minetest.get_node +local minetest_line_of_sight = minetest.line_of_sight local state_list_wandering = {"stand", "walk"} +local DOUBLE_PI = math.pi * 2 +local EIGHTH_PI = DOUBLE_PI * 0.125 +--this is basically reverse jump_check +local cliff_check = function(self,dtime) + local pos = self.object:get_pos() + pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + + local free_fall, blocker = minetest_line_of_sight( + {x = pos.x + dir.x, y = pos.y, z = pos.z + dir.z}, + {x = pos.x + dir.x, y = pos.y - self.fear_height, z = pos.z + dir.z}) + + return free_fall +end + +--a simple helper function which is too small to move into movement.lua +local quick_rotate_45 = function(self,dtime) + self.yaw = self.yaw + EIGHTH_PI + if self.yaw > DOUBLE_PI then + self.yaw = self.yaw - DOUBLE_PI + end +end --check if a mob needs to jump local jump_check = function(self,dtime) @@ -84,6 +110,17 @@ local state_execution = function(self,dtime) --check for nodes to jump over jump_check(self) + --turn if on the edge of cliff + --(this is written like this because unlike + --jump_check which simply tells the mob to jump + --this requires a mob to turn, removing the + --ease of a full implementation for it in a single + --function) + if cliff_check(self,dtime) then + --turn 45 degrees if so + quick_rotate_45(self,dtime) + end + --print("walk") elseif self.state == "run" then From 6c5393427f72c082a5c85514cb3b54aa4a9ce45f Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 15:39:39 -0400 Subject: [PATCH 045/117] Smooth out mob cliff check and check if falling before cliff check --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 08d6916f57..06c6d00acb 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -12,17 +12,26 @@ local minetest_line_of_sight = minetest.line_of_sight local state_list_wandering = {"stand", "walk"} local DOUBLE_PI = math.pi * 2 -local EIGHTH_PI = DOUBLE_PI * 0.125 +local THIRTY_SECONDTH_PI = DOUBLE_PI * 0.03125 --this is basically reverse jump_check local cliff_check = function(self,dtime) + --mobs will flip out if they are falling without this + if self.object:get_velocity().y ~= 0 then + return false + end + local pos = self.object:get_pos() - pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + dir = vector_multiply(dir,radius) + local free_fall, blocker = minetest_line_of_sight( {x = pos.x + dir.x, y = pos.y, z = pos.z + dir.z}, {x = pos.x + dir.x, y = pos.y - self.fear_height, z = pos.z + dir.z}) @@ -32,7 +41,7 @@ end --a simple helper function which is too small to move into movement.lua local quick_rotate_45 = function(self,dtime) - self.yaw = self.yaw + EIGHTH_PI + self.yaw = self.yaw + THIRTY_SECONDTH_PI if self.yaw > DOUBLE_PI then self.yaw = self.yaw - DOUBLE_PI end From a6a54b34140c279d7a9ff3db5b21f1be0ead15f8 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 15:49:03 -0400 Subject: [PATCH 046/117] Make mobs not jump if against a wall --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 06c6d00acb..7b154f0d86 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -60,9 +60,17 @@ local jump_check = function(self,dtime) vector_multiply(dir, radius) + --only jump if there's a node and a non-solid node above it local test_dir = vector.add(pos,dir) - if minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 then + local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 + + test_dir.y = test_dir.y + 1 + + local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0 + + + if green_flag_1 and green_flag_2 then mobs.jump(self) end end From fb9a55e562c3e4102fa4e02603f93d1c78e397ad Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 15:55:11 -0400 Subject: [PATCH 047/117] Make jump_check more modular and allow mobs to turn if at a wall --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 7b154f0d86..adffc69514 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -70,9 +70,14 @@ local jump_check = function(self,dtime) local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0 - if green_flag_1 and green_flag_2 then - mobs.jump(self) + if green_flag_1 and green_flag_2 then -- can jump over node + return(1) + elseif green_flag_1 and not green_flag_2 then --wall in front of + return(2) end + + --nothing to jump over + return(0) end @@ -125,7 +130,11 @@ local state_execution = function(self,dtime) mobs.set_velocity(self,1) --check for nodes to jump over - jump_check(self) + local node_in_front_of = jump_check(self) + + if node_in_front_of == 1 then + mobs.jump(self) + end --turn if on the edge of cliff --(this is written like this because unlike @@ -133,7 +142,7 @@ local state_execution = function(self,dtime) --this requires a mob to turn, removing the --ease of a full implementation for it in a single --function) - if cliff_check(self,dtime) then + if node_in_front_of == 2 or cliff_check(self,dtime) then --turn 45 degrees if so quick_rotate_45(self,dtime) end From 57b293de2b02be81ff3e17e620807c653fe9b625 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 16:37:15 -0400 Subject: [PATCH 048/117] Make mobs gravity equal to player's --- mods/ENTITIES/mcl_mobs/api/api.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index e8c42b5735..9de87408a6 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -58,6 +58,8 @@ local DEATH_DELAY = 0.5 local DEFAULT_FALL_SPEED = -10 local FLOP_HEIGHT = 5.0 local FLOP_HOR_SPEED = 1.5 +local GRAVITY = minetest_settings:get("movement_gravity") + 9.81 + local MOB_CAP = {} MOB_CAP.hostile = 70 @@ -308,6 +310,7 @@ function mobs:register_mob(name, def) stand_timer = 0, wandering = true, current_animation = "", + gravity = GRAVITY, --set_animation = mobs.set_animation, --end j4i stuff @@ -322,7 +325,7 @@ function mobs:register_mob(name, def) child = def.child or false, texture_mods = {}, shoot_arrow = def.shoot_arrow, - sounds_child = def.sounds_child, + sounds_child = def.sounds_child, explosion_strength = def.explosion_strength, suffocation_timer = 0, follow_velocity = def.follow_velocity or 2.4, @@ -349,7 +352,7 @@ function mobs:register_mob(name, def) --on_detach_child = mob_detach_child, on_activate = function(self, staticdata, dtime) - self.object:set_acceleration(vector_new(0,-9.81, 0)) + self.object:set_acceleration(vector_new(0,-GRAVITY, 0)) return mobs.mob_activate(self, staticdata, def, dtime) end, From cadd53c103f4047069f581abdc033d2def4ed2dd Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 16:39:03 -0400 Subject: [PATCH 049/117] Adjust mob jumping default to account for higher gravity --- mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 72ee3824d7..390a867789 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -60,7 +60,7 @@ mobs.jump = function(self, velocity) return end - velocity = velocity or 5 + velocity = velocity or 8 self.object:add_velocity(vector_new(0,velocity,0)) end \ No newline at end of file From 8ca5f221ec9ce534e91f7094193b4ec951e743b1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 18:13:54 -0400 Subject: [PATCH 050/117] clean up ai.lua --- .../mcl_mobs/api/mob_functions/ai.lua | 166 ----------------- .../api/mob_functions/backup_code_api.lua | 169 ++++++++++++++++++ 2 files changed, 169 insertions(+), 166 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index adffc69514..4907063956 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -175,12 +175,6 @@ mobs.mob_step = function(self, dtime) --print(self.object:get_yaw()) - --if self.state == "die" then - -- print("need custom die stop moving thing") - -- return - --end - - state_switch(self, dtime) state_execution(self,dtime) @@ -191,165 +185,5 @@ mobs.mob_step = function(self, dtime) mobs.collision(self) end - - --if not self.fire_resistant then - -- mcl_burning.tick(self.object, dtime) - --end - - --if use_cmi then - --cmi.notify_step(self.object, dtime) - --end - - --local pos = self.object:get_pos() - --local yaw = 0 - - --if mobs_debug then - --update_tag(self) - --end - - - - --if self.jump_sound_cooloff > 0 then - -- self.jump_sound_cooloff = self.jump_sound_cooloff - dtime - --end - - --if self.opinion_sound_cooloff > 0 then - -- self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime - --end - - --if falling(self, pos) then - -- Return if mob died after falling - -- return - --end - - - -- run custom function (defined in mob lua file) - --if self.do_custom then - - -- when false skip going any further - --if self.do_custom(self, dtime) == false then - -- return - --end - --end - - -- knockback timer - --if self.pause_timer > 0 then - - -- self.pause_timer = self.pause_timer - dtime - - -- return - --end - - -- attack timer - --self.timer = self.timer + dtime - - --[[ - if self.state ~= "attack" then - - if self.timer < 1 then - print("returning>>error code 1") - return - end - - self.timer = 0 - end - ]]-- - - -- never go over 100 - --if self.timer > 100 then - -- self.timer = 1 - --end - - -- mob plays random sound at times - --if math_random(1, 70) == 1 then - -- mob_sound(self, "random", true) - --end - - -- environmental damage timer (every 1 second) - --self.env_damage_timer = self.env_damage_timer + dtime - - --if (self.state == "attack" and self.env_damage_timer > 1) - --or self.state ~= "attack" then - -- - -- self.env_damage_timer = 0 - -- - -- -- check for environmental damage (water, fire, lava etc.) - -- if do_env_damage(self) then - -- return - -- end - -- - -- node replace check (cow eats grass etc.) - -- replace(self, pos) - --end - - --monster_attack(self) - - --npc_attack(self) - - --breed(self) - - --do_jump(self) - - --runaway_from(self) - - - --if is_at_water_danger(self) and self.state ~= "attack" then - -- if math_random(1, 10) <= 6 then - -- set_velocity(self, 0) - -- self.state = "stand" - -- set_animation(self, "stand") - -- yaw = yaw + math_random(-0.5, 0.5) - -- yaw = set_yaw(self, yaw, 8) - -- end - --end - - - -- Add water flowing for mobs from mcl_item_entity - --[[ - local p, node, nn, def - p = self.object:get_pos() - node = minetest_get_node_or_nil(p) - if node then - nn = node.name - def = minetest_registered_nodes[nnenable_physicss if not on/in flowing liquid - self._flowing = false - enable_physics(self.object, self, true) - return - end - - --Mob following code. - follow_flop(self) - - - if is_at_cliff_or_danger(self) then - set_velocity(self, 0) - self.state = "stand" - set_animation(self, "stand") - local yaw = self.object:get_yaw() or 0 - yaw = set_yaw(self, yaw + 0.78, 8) - end - - -- Despawning: when lifetimer expires, remove mob - if remove_far - and self.can_despawn == true - and ((not self.nametag) or (self.nametag == "")) - and self.state ~= "attack" - and self.following == nil then - - self.lifetimer = self.lifetimer - dtime - if self.despawn_immediately or self.lifetimer <= 0 then - minetest.log("action", "Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1)) - mcl_burning.extinguish(self.object) - self.object:remove() - elseif self.lifetimer <= 10 then - if math_random(10) < 4 then - self.despawn_immediately = true - else - self.lifetimer = 20 - end - end - end - ]]-- - self.old_velocity = self.object:get_velocity() end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua index eb1389e371..292a27ec0d 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua @@ -3297,3 +3297,172 @@ end function mobs:yaw(self, yaw, delay, dtime) set_yaw(self, yaw, delay, dtime) end + + +mob_step = function() + + --if self.state == "die" then + -- print("need custom die stop moving thing") + -- return + --end + + --if not self.fire_resistant then + -- mcl_burning.tick(self.object, dtime) + --end + + --if use_cmi then + --cmi.notify_step(self.object, dtime) + --end + + --local pos = self.object:get_pos() + --local yaw = 0 + + --if mobs_debug then + --update_tag(self) + --end + + + + --if self.jump_sound_cooloff > 0 then + -- self.jump_sound_cooloff = self.jump_sound_cooloff - dtime + --end + + --if self.opinion_sound_cooloff > 0 then + -- self.opinion_sound_cooloff = self.opinion_sound_cooloff - dtime + --end + + --if falling(self, pos) then + -- Return if mob died after falling + -- return + --end + + + -- run custom function (defined in mob lua file) + --if self.do_custom then + + -- when false skip going any further + --if self.do_custom(self, dtime) == false then + -- return + --end + --end + + -- knockback timer + --if self.pause_timer > 0 then + + -- self.pause_timer = self.pause_timer - dtime + + -- return + --end + + -- attack timer + --self.timer = self.timer + dtime + + --[[ + if self.state ~= "attack" then + + if self.timer < 1 then + print("returning>>error code 1") + return + end + + self.timer = 0 + end + ]]-- + + -- never go over 100 + --if self.timer > 100 then + -- self.timer = 1 + --end + + -- mob plays random sound at times + --if math_random(1, 70) == 1 then + -- mob_sound(self, "random", true) + --end + + -- environmental damage timer (every 1 second) + --self.env_damage_timer = self.env_damage_timer + dtime + + --if (self.state == "attack" and self.env_damage_timer > 1) + --or self.state ~= "attack" then + -- + -- self.env_damage_timer = 0 + -- + -- -- check for environmental damage (water, fire, lava etc.) + -- if do_env_damage(self) then + -- return + -- end + -- + -- node replace check (cow eats grass etc.) + -- replace(self, pos) + --end + + --monster_attack(self) + + --npc_attack(self) + + --breed(self) + + --do_jump(self) + + --runaway_from(self) + + + --if is_at_water_danger(self) and self.state ~= "attack" then + -- if math_random(1, 10) <= 6 then + -- set_velocity(self, 0) + -- self.state = "stand" + -- set_animation(self, "stand") + -- yaw = yaw + math_random(-0.5, 0.5) + -- yaw = set_yaw(self, yaw, 8) + -- end + --end + + + -- Add water flowing for mobs from mcl_item_entity + --[[ + local p, node, nn, def + p = self.object:get_pos() + node = minetest_get_node_or_nil(p) + if node then + nn = node.name + def = minetest_registered_nodes[nnenable_physicss if not on/in flowing liquid + self._flowing = false + enable_physics(self.object, self, true) + return + end + + --Mob following code. + follow_flop(self) + + + if is_at_cliff_or_danger(self) then + set_velocity(self, 0) + self.state = "stand" + set_animation(self, "stand") + local yaw = self.object:get_yaw() or 0 + yaw = set_yaw(self, yaw + 0.78, 8) + end + + -- Despawning: when lifetimer expires, remove mob + if remove_far + and self.can_despawn == true + and ((not self.nametag) or (self.nametag == "")) + and self.state ~= "attack" + and self.following == nil then + + self.lifetimer = self.lifetimer - dtime + if self.despawn_immediately or self.lifetimer <= 0 then + minetest.log("action", "Mob "..self.name.." despawns in mob_step at "..minetest.pos_to_string(pos, 1)) + mcl_burning.extinguish(self.object) + self.object:remove() + elseif self.lifetimer <= 10 then + if math_random(10) < 4 then + self.despawn_immediately = true + else + self.lifetimer = 20 + end + end + end + ]]-- + +end \ No newline at end of file From ed456ecb47d788efe9aa526849110015e9c04e9a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 18:17:51 -0400 Subject: [PATCH 051/117] Make mobs not fear cliffs if fear_height is 0 --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 4907063956..080d02b226 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -142,7 +142,7 @@ local state_execution = function(self,dtime) --this requires a mob to turn, removing the --ease of a full implementation for it in a single --function) - if node_in_front_of == 2 or cliff_check(self,dtime) then + if node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then --turn 45 degrees if so quick_rotate_45(self,dtime) end From c761db86c7e67aab27d3806a76b7a58504a7d5c6 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 18:29:42 -0400 Subject: [PATCH 052/117] re-arrange mob logic for random wandering --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 080d02b226..6eb0b99d94 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -126,25 +126,29 @@ local state_execution = function(self,dtime) --enable rotation locking mobs.movement_rotation_lock(self) - --set the velocity of the mob - mobs.set_velocity(self,1) + --check for nodes to jump over local node_in_front_of = jump_check(self) if node_in_front_of == 1 then mobs.jump(self) - end - --turn if on the edge of cliff --(this is written like this because unlike --jump_check which simply tells the mob to jump --this requires a mob to turn, removing the --ease of a full implementation for it in a single --function) - if node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then + elseif node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then --turn 45 degrees if so quick_rotate_45(self,dtime) + mobs.set_velocity(self,0) + end + + --only move forward if path is clear + if node_in_front_of == 0 or node_in_front_of == 1 then + --set the velocity of the mob + mobs.set_velocity(self,1) end --print("walk") From 05d06a4c8f0128ac5edd21b8096bb75553c1f89e Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 18:36:23 -0400 Subject: [PATCH 053/117] Add comment to state_execution --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 6eb0b99d94..e89aba317a 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -126,8 +126,6 @@ local state_execution = function(self,dtime) --enable rotation locking mobs.movement_rotation_lock(self) - - --check for nodes to jump over local node_in_front_of = jump_check(self) @@ -142,6 +140,7 @@ local state_execution = function(self,dtime) elseif node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then --turn 45 degrees if so quick_rotate_45(self,dtime) + --stop the mob so it doesn't fall off mobs.set_velocity(self,0) end From ce7f4918b061fa9a4d46045a389497cb0da1a5ee Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 19:35:19 -0400 Subject: [PATCH 054/117] Re-organize comments --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index e89aba317a..ed7998c08b 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -69,10 +69,11 @@ local jump_check = function(self,dtime) local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0 - - if green_flag_1 and green_flag_2 then -- can jump over node + if green_flag_1 and green_flag_2 then + --can jump over node return(1) - elseif green_flag_1 and not green_flag_2 then --wall in front of + elseif green_flag_1 and not green_flag_2 then + --wall in front of mob return(2) end @@ -131,6 +132,7 @@ local state_execution = function(self,dtime) if node_in_front_of == 1 then mobs.jump(self) + --turn if on the edge of cliff --(this is written like this because unlike --jump_check which simply tells the mob to jump From 9d6d042ee325a010d97abdff7efc37f3dcf46b5e Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 19:37:01 -0400 Subject: [PATCH 055/117] Fix formatting in ai.lua --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index ed7998c08b..93e11e35be 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -23,11 +23,8 @@ local cliff_check = function(self,dtime) end local pos = self.object:get_pos() - local dir = minetest_yaw_to_dir(self.yaw) - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 dir = vector_multiply(dir,radius) From 15ea9c1c71f3e4d4dd24ce145d385f8457e4905e Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 19:59:20 -0400 Subject: [PATCH 056/117] Implement self walking velocity for walking state --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 93e11e35be..982641e738 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -146,7 +146,7 @@ local state_execution = function(self,dtime) --only move forward if path is clear if node_in_front_of == 0 or node_in_front_of == 1 then --set the velocity of the mob - mobs.set_velocity(self,1) + mobs.set_velocity(self,self.walk_velocity) end --print("walk") From 6db4511dd5b038cd95c7ea196559bb25a53246e9 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 20:06:55 -0400 Subject: [PATCH 057/117] Add notes --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 2 +- mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 982641e738..73f5beff3c 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -167,7 +167,7 @@ end - +--the main loop mobs.mob_step = function(self, dtime) --do not continue if non-existent diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua new file mode 100644 index 0000000000..5ba67b28c5 --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua @@ -0,0 +1 @@ +--make mobs scan players and check distance then if direct line of sight then add to list and go after whichever one is closer \ No newline at end of file From 52c3db041e602ebd0861a0b86c55b35662c8c33a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 20:32:05 -0400 Subject: [PATCH 058/117] Add in fly state prep for mobs --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 +- .../mcl_mobs/api/mob_functions/ai.lua | 88 ++++++++++++++++--- 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 9de87408a6..330fdcd849 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -218,7 +218,7 @@ function mobs:register_mob(name, def) xp_max = def.xp_max or 0, xp_timestamp = 0, breath_max = def.breath_max or 15, - breathes_in_water = def.breathes_in_water or false, + breathes_in_water = def.breathes_in_water or false, physical = true, collisionbox = collisionbox, collide_with_objects = def.collide_with_objects or false, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 73f5beff3c..b1c6d293d9 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -8,13 +8,19 @@ local minetest_get_item_group = minetest.get_item_group local minetest_get_node = minetest.get_node local minetest_line_of_sight = minetest.line_of_sight - -local state_list_wandering = {"stand", "walk"} - local DOUBLE_PI = math.pi * 2 local THIRTY_SECONDTH_PI = DOUBLE_PI * 0.03125 +--[[ + _ _ +| | | | +| | __ _ _ __ __| | +| | / _` | '_ \ / _` | +| |___| (_| | | | | (_| | +\_____/\__,_|_| |_|\__,_| +]] + --this is basically reverse jump_check local cliff_check = function(self,dtime) --mobs will flip out if they are falling without this @@ -56,7 +62,6 @@ local jump_check = function(self,dtime) vector_multiply(dir, radius) - --only jump if there's a node and a non-solid node above it local test_dir = vector.add(pos,dir) @@ -81,19 +86,23 @@ end -- state switching logic (stand, walk, run, attacks) -local state_switch = function(self, dtime) +local land_state_list_wandering = {"stand", "walk"} + +local land_state_switch = function(self, dtime) self.state_timer = self.state_timer - dtime if self.wandering and self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() - self.state = state_list_wandering[math.random(1,#state_list_wandering)] + self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)] end + end --- states are executed here (goto would have been helpful :<) -local state_execution = function(self,dtime) +-- states are executed here +local land_state_execution = function(self,dtime) --local yaw = self.object:get_yaw() or 0 + if self.state == "stand" then --do animation @@ -102,8 +111,6 @@ local state_execution = function(self,dtime) --set the velocity of the mob mobs.set_velocity(self,0) - --print("stand") - elseif self.state == "walk" then self.walk_timer = self.walk_timer - dtime @@ -149,8 +156,6 @@ local state_execution = function(self,dtime) mobs.set_velocity(self,self.walk_velocity) end - --print("walk") - elseif self.state == "run" then print("run") @@ -166,6 +171,53 @@ end +--[[ +______ _ _ _______ _ _ +| ___| | (_) / / ___| (_) (_) +| |_ | |_ _ _ _ __ __ _ / /\ `--.__ ___ _ __ ___ _ __ ___ _ _ __ __ _ +| _| | | | | | | '_ \ / _` | / / `--. \ \ /\ / / | '_ ` _ \| '_ ` _ \| | '_ \ / _` | +| | | | |_| | | | | | (_| |/ / /\__/ /\ V V /| | | | | | | | | | | | | | | | (_| | +\_| |_|\__, |_|_| |_|\__, /_/ \____/ \_/\_/ |_|_| |_| |_|_| |_| |_|_|_| |_|\__, | + __/ | __/ | __/ | + |___/ |___/ |___/ +]]-- + + + +-- state switching logic (stand, walk, run, attacks) +local fly_state_list_wandering = {"stand", "walk"} + +local fly_state_switch = function(self, dtime) + self.state_timer = self.state_timer - dtime + if self.wandering and self.state_timer <= 0 then + self.state_timer = math.random(4,10) + math.random() + self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)] + end + +end + + + +local fly_state_execution = function(self,dtime) + + +end + +local fly_state_switch = function(self, dtime) + + +end + +--[[ +___ ___ _ _ _ +| \/ | (_) | | (_) +| . . | __ _ _ _ __ | | ___ __ _ _ ___ +| |\/| |/ _` | | '_ \ | | / _ \ / _` | |/ __| +| | | | (_| | | | | | | |___| (_) | (_| | | (__ +\_| |_/\__,_|_|_| |_| \_____/\___/ \__, |_|\___| + __/ | + |___/ +]] --the main loop mobs.mob_step = function(self, dtime) @@ -177,9 +229,17 @@ mobs.mob_step = function(self, dtime) --print(self.object:get_yaw()) - state_switch(self, dtime) - state_execution(self,dtime) + + --swimming/flying + if self.fly then + fly_state_switch(self, dtime) + fly_state_execution(self, dtime) + --regular mobs that walk around + else + land_state_switch(self, dtime) + land_state_execution(self,dtime) + end -- can mob be pushed, if so calculate direction -- do this last (overrides everything) From 84ca7681fc9ee3e9945488865678b2b82eb0a22d Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 20:47:16 -0400 Subject: [PATCH 059/117] Make squids fly in water flowing and water source --- .../mcl_mobs/api/mob_functions/ai.lua | 37 ++++++++++++++++--- mods/ENTITIES/mobs_mc/0_gameconfig.lua | 2 + mods/ENTITIES/mobs_mc/squid.lua | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index b1c6d293d9..4313c29ce0 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -185,13 +185,13 @@ ______ _ _ _______ _ _ -- state switching logic (stand, walk, run, attacks) -local fly_state_list_wandering = {"stand", "walk"} +local fly_state_list_wandering = {"stand", "fly"} local fly_state_switch = function(self, dtime) self.state_timer = self.state_timer - dtime if self.wandering and self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() - self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)] + self.state = fly_state_list_wandering[math.random(1,#fly_state_list_wandering)] end end @@ -200,13 +200,38 @@ end local fly_state_execution = function(self,dtime) + local pos = self.object:get_pos() + local current_node = minetest_get_node(pos).name + local inside_swim_node = false + + for _,id in pairs(self.fly_in) do + if id == current_node then + inside_swim_node = true + break + end + end + + print(inside_swim_node) + + if self.state == "stand" then + + --do animation + --mobs.set_mob_animation(self, "stand") + + --set the velocity of the mob + --mobs.set_velocity(self,0) + + --print("standing") + + elseif self.state == "fly" then + + + --print("flying") + + end end -local fly_state_switch = function(self, dtime) - - -end --[[ ___ ___ _ _ _ diff --git a/mods/ENTITIES/mobs_mc/0_gameconfig.lua b/mods/ENTITIES/mobs_mc/0_gameconfig.lua index c92ccbba52..3476bee4c7 100644 --- a/mods/ENTITIES/mobs_mc/0_gameconfig.lua +++ b/mods/ENTITIES/mobs_mc/0_gameconfig.lua @@ -81,7 +81,9 @@ mobs_mc.items = { gunpowder = "tnt:gunpowder", flint_and_steel = "fire:flint_and_steel", water_source = "default:water_source", + water_flowing = "default:water_flowing", river_water_source = "default:river_water_source", + water_flowing = "default:river_water_flowing", black_dye = "dye:black", poppy = "flowers:rose", dandelion = "flowers:dandelion_yellow", diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index cf794ea5bf..fbec650ddb 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -48,7 +48,7 @@ mobs:register_mob("mobs_mc:squid", { visual_size = {x=3, y=3}, makes_footstep_sound = false, fly = true, - fly_in = { mobs_mc.items.water_source, mobs_mc.items.river_water_source }, + fly_in = { mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source }, breathes_in_water = true, jump = false, view_range = 16, From f1141aed9fa52bf57e8867fdb3ffb520793dab07 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 21:08:54 -0400 Subject: [PATCH 060/117] Make mobs flop when outside of flying node --- .../mcl_mobs/api/mob_functions/ai.lua | 37 ++++++++++++------ .../mcl_mobs/api/mob_functions/movement.lua | 39 ++++++++++++++++++- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 4313c29ce0..c77e0b1a59 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -193,41 +193,54 @@ local fly_state_switch = function(self, dtime) self.state_timer = math.random(4,10) + math.random() self.state = fly_state_list_wandering[math.random(1,#fly_state_list_wandering)] end - end +--this is going to need some more logic gates because birds can flop around +local flop = function(self,dtime) + mobs.flop(self) +end + +-- states are executed here local fly_state_execution = function(self,dtime) local pos = self.object:get_pos() local current_node = minetest_get_node(pos).name - local inside_swim_node = false + local inside_fly_node = false + --quick scan everything to see if inside fly node for _,id in pairs(self.fly_in) do if id == current_node then - inside_swim_node = true + inside_fly_node = true break end end - print(inside_swim_node) + - if self.state == "stand" then + --fly properly if inside fly node + if inside_fly_node then + if self.state == "stand" then - --do animation - --mobs.set_mob_animation(self, "stand") + --do animation + --mobs.set_mob_animation(self, "stand") - --set the velocity of the mob - --mobs.set_velocity(self,0) + --set the velocity of the mob + --mobs.set_velocity(self,0) - --print("standing") + --print("standing") - elseif self.state == "fly" then + elseif self.state == "fly" then - --print("flying") + --print("flying") + end + --flop around if not inside fly node + else + --print("flopping") + flop(self,dtime) end end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 390a867789..09e21f4707 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -1,10 +1,15 @@ local math_pi = math.pi local math_sin = math.sin local math_cos = math.cos +local math_random = math.random +local DOUBLE_PI = math_pi * 2 -- localize vector functions -local vector_new = vector.new -local vector_length = vector.length +local vector_new = vector.new +local vector_length = vector.length +local vector_multiply = vector.multiply + +local minetest_yaw_to_dir = minetest.yaw_to_dir -- move mob in facing direction --this has been modified to be internal @@ -60,7 +65,37 @@ mobs.jump = function(self, velocity) return end + --fallback velocity to allow modularity velocity = velocity or 8 self.object:add_velocity(vector_new(0,velocity,0)) +end + +--make mobs flop +mobs.flop = function(self, velocity) + + if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then + return false + end + + mobs.set_velocity(self, 0) + + --fallback velocity to allow modularity + velocity = velocity or 8 + + --create a random direction (2d yaw) + local dir = DOUBLE_PI * math_random() + + --create a random force value + local force = math_random(0,3) + math_random() + + --convert the yaw to a direction vector then multiply it times the force + local final_additional_force = vector_multiply(minetest_yaw_to_dir(dir), force) + + --place in the "flop" velocity to make the mob flop + final_additional_force.y = velocity + + self.object:add_velocity(final_additional_force) + + return true end \ No newline at end of file From dda7839d8c4c2292e9c8d6472faf38372654d886 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Fri, 16 Apr 2021 21:43:02 -0400 Subject: [PATCH 061/117] Add in prototype swimming --- .../mcl_mobs/api/mob_functions/ai.lua | 44 ++++++++++++++++++- .../mcl_mobs/api/mob_functions/movement.lua | 32 ++++++++++++++ mods/ENTITIES/mobs_mc/squid.lua | 1 + 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index c77e0b1a59..4a19d00670 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -2,6 +2,7 @@ local math_random = math.random local vector_multiply = vector.multiply local vector_add = vector.add +local vector_new = vector.new local minetest_yaw_to_dir = minetest.yaw_to_dir local minetest_get_item_group = minetest.get_item_group @@ -201,11 +202,32 @@ local flop = function(self,dtime) mobs.flop(self) end +--this is to swap the built in engine acceleration modifier +local fly_physics_swapper = function(self,inside_fly_node) + --push non-existing physics switch to new mobs + self.fly_physics_switch = self.fly_physics_switch or not inside_fly_node + + --should be flying, gravity is applied, switch to floating + if inside_fly_node and not self.fly_physics_switch then + self.object:set_acceleration(vector_new(0,0,0)) + self.fly_physics_switch = true + --not be flying, gravity isn't applied, switch to falling + elseif not inside_fly_node and self.fly_physics_switch then + self.pitch = 0 + self.object:set_acceleration(vector_new(0,-self.gravity,0)) + self.fly_physics_switch = false + end +end + + +local random_pitch_multiplier = {-1,1} -- states are executed here local fly_state_execution = function(self,dtime) local pos = self.object:get_pos() + + pos.y = pos.y + self.object:get_properties().collisionbox[5] local current_node = minetest_get_node(pos).name local inside_fly_node = false @@ -217,10 +239,12 @@ local fly_state_execution = function(self,dtime) end end - + --turn gravity on or off + fly_physics_swapper(self,inside_fly_node) --fly properly if inside fly node if inside_fly_node then + if self.state == "stand" then --do animation @@ -231,11 +255,27 @@ local fly_state_execution = function(self,dtime) --print("standing") + mobs.set_fly_velocity(self,0) + elseif self.state == "fly" then + self.walk_timer = self.walk_timer - dtime - --print("flying") + --reset the walk timer + if self.walk_timer <= 0 then + + --re-randomize the walk timer + self.walk_timer = math.random(1,6) + math.random() + + --set the mob into a random direction + self.yaw = (math_random() * (math.pi * 2)) + --create a truly random pitch, since there is no easy access to pitch math that I can find + self.pitch = math_random() * random_pitch_multiplier[math_random(1,2)] + end + + + mobs.set_fly_velocity(self,self.walk_velocity) end --flop around if not inside fly node else diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 09e21f4707..681d97a1e0 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -98,4 +98,36 @@ mobs.flop = function(self, velocity) self.object:add_velocity(final_additional_force) return true +end + + + +-- move mob in facing direction +--this has been modified to be internal +--internal = lua (self.yaw) +--engine = c++ (self.object:get_yaw()) +mobs.set_fly_velocity = function(self, v) + + local yaw = (self.yaw or 0) + local pitch = (self.pitch or 0) + + local current_velocity = self.object:get_velocity() + + local goal_velocity = { + x = (math_sin(yaw) * -v), + y = pitch, + z = (math_cos(yaw) * v), + } + + + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + + if vector_length(new_velocity_addition) > vector_length(goal_velocity) then + vector.multiply(new_velocity_addition, (vector_length(goal_velocity) / vector_length(new_velocity_addition))) + end + + --smooths out mobs a bit + if vector_length(new_velocity_addition) >= 0.0001 then + self.object:add_velocity(new_velocity_addition) + end end \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index fbec650ddb..f650472fc7 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -16,6 +16,7 @@ mobs:register_mob("mobs_mc:squid", { xp_min = 1, xp_max = 3, armor = 100, + rotate = 270, -- FIXME: If the squid is near the floor, it turns black collisionbox = {-0.4, 0.0, -0.4, 0.4, 0.9, 0.4}, visual = "mesh", From 5365dec19a8a088263916a3686f27859be51e870 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:01:27 -0400 Subject: [PATCH 062/117] Adjust "flying" vector checks for mobs --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 9 ++------- mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua | 4 ++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 4a19d00670..fe091b5d2e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -205,18 +205,13 @@ end --this is to swap the built in engine acceleration modifier local fly_physics_swapper = function(self,inside_fly_node) - --push non-existing physics switch to new mobs - self.fly_physics_switch = self.fly_physics_switch or not inside_fly_node - --should be flying, gravity is applied, switch to floating - if inside_fly_node and not self.fly_physics_switch then + if inside_fly_node and self.object:get_acceleration().y ~= 0 then self.object:set_acceleration(vector_new(0,0,0)) - self.fly_physics_switch = true --not be flying, gravity isn't applied, switch to falling - elseif not inside_fly_node and self.fly_physics_switch then + elseif not inside_fly_node and self.object:get_acceleration().y == 0 then self.pitch = 0 self.object:set_acceleration(vector_new(0,-self.gravity,0)) - self.fly_physics_switch = false end end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 681d97a1e0..72f93ea242 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -111,6 +111,10 @@ mobs.set_fly_velocity = function(self, v) local yaw = (self.yaw or 0) local pitch = (self.pitch or 0) + if v == 0 then + pitch = 0 + end + local current_velocity = self.object:get_velocity() local goal_velocity = { From 061602d9d46d4e4607e407c064070709ef99f9b7 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:28:07 -0400 Subject: [PATCH 063/117] Overhaul separation of swimming and flying for ease of use with writing mobs api --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 + .../mcl_mobs/api/mob_functions/ai.lua | 62 +++++++++---------- .../mcl_mobs/api/mob_functions/movement.lua | 29 ++++++++- mods/ENTITIES/mobs_mc/squid.lua | 3 +- 4 files changed, 61 insertions(+), 35 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 330fdcd849..47804b0d00 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -311,6 +311,8 @@ function mobs:register_mob(name, def) wandering = true, current_animation = "", gravity = GRAVITY, + swim = def.swim, + swim_in = def.swim_in or {mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source}, --set_animation = mobs.set_animation, --end j4i stuff diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index fe091b5d2e..794f8d2f16 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -173,26 +173,24 @@ end --[[ -______ _ _ _______ _ _ -| ___| | (_) / / ___| (_) (_) -| |_ | |_ _ _ _ __ __ _ / /\ `--.__ ___ _ __ ___ _ __ ___ _ _ __ __ _ -| _| | | | | | | '_ \ / _` | / / `--. \ \ /\ / / | '_ ` _ \| '_ ` _ \| | '_ \ / _` | -| | | | |_| | | | | | (_| |/ / /\__/ /\ V V /| | | | | | | | | | | | | | | | (_| | -\_| |_|\__, |_|_| |_|\__, /_/ \____/ \_/\_/ |_|_| |_| |_|_| |_| |_|_|_| |_|\__, | - __/ | __/ | __/ | - |___/ |___/ |___/ + _____ _ +/ ___| (_) +\ `--.__ ___ _ __ ___ + `--. \ \ /\ / / | '_ ` _ \ +/\__/ /\ V V /| | | | | | | +\____/ \_/\_/ |_|_| |_| |_| ]]-- -- state switching logic (stand, walk, run, attacks) -local fly_state_list_wandering = {"stand", "fly"} +local swim_state_list_wandering = {"stand", "swim"} -local fly_state_switch = function(self, dtime) +local swim_state_switch = function(self, dtime) self.state_timer = self.state_timer - dtime if self.wandering and self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() - self.state = fly_state_list_wandering[math.random(1,#fly_state_list_wandering)] + self.state = swim_state_list_wandering[math.random(1,#swim_state_list_wandering)] end end @@ -203,13 +201,13 @@ local flop = function(self,dtime) end --this is to swap the built in engine acceleration modifier -local fly_physics_swapper = function(self,inside_fly_node) +local swim_physics_swapper = function(self,inside_swim_node) - --should be flying, gravity is applied, switch to floating - if inside_fly_node and self.object:get_acceleration().y ~= 0 then + --should be swimming, gravity is applied, switch to floating + if inside_swim_node and self.object:get_acceleration().y ~= 0 then self.object:set_acceleration(vector_new(0,0,0)) - --not be flying, gravity isn't applied, switch to falling - elseif not inside_fly_node and self.object:get_acceleration().y == 0 then + --not be swim, gravity isn't applied, switch to falling + elseif not inside_swim_node and self.object:get_acceleration().y == 0 then self.pitch = 0 self.object:set_acceleration(vector_new(0,-self.gravity,0)) end @@ -218,27 +216,27 @@ end local random_pitch_multiplier = {-1,1} -- states are executed here -local fly_state_execution = function(self,dtime) +local swim_state_execution = function(self,dtime) local pos = self.object:get_pos() pos.y = pos.y + self.object:get_properties().collisionbox[5] local current_node = minetest_get_node(pos).name - local inside_fly_node = false + local inside_swim_node = false - --quick scan everything to see if inside fly node - for _,id in pairs(self.fly_in) do + --quick scan everything to see if inside swim node + for _,id in pairs(self.swim_in) do if id == current_node then - inside_fly_node = true + inside_swim_node = true break end end --turn gravity on or off - fly_physics_swapper(self,inside_fly_node) + swim_physics_swapper(self,inside_swim_node) - --fly properly if inside fly node - if inside_fly_node then + --swim properly if inside swim node + if inside_swim_node then if self.state == "stand" then @@ -250,9 +248,9 @@ local fly_state_execution = function(self,dtime) --print("standing") - mobs.set_fly_velocity(self,0) + mobs.set_swim_velocity(self,0) - elseif self.state == "fly" then + elseif self.state == "swim" then self.walk_timer = self.walk_timer - dtime @@ -270,9 +268,9 @@ local fly_state_execution = function(self,dtime) end - mobs.set_fly_velocity(self,self.walk_velocity) + mobs.set_swim_velocity(self,self.walk_velocity) end - --flop around if not inside fly node + --flop around if not inside swim node else --print("flopping") flop(self,dtime) @@ -304,10 +302,10 @@ mobs.mob_step = function(self, dtime) - --swimming/flying - if self.fly then - fly_state_switch(self, dtime) - fly_state_execution(self, dtime) + --swimming + if self.swim then + swim_state_switch(self, dtime) + swim_state_execution(self, dtime) --regular mobs that walk around else land_state_switch(self, dtime) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 72f93ea242..0cf6a6ab23 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -11,6 +11,17 @@ local vector_multiply = vector.multiply local minetest_yaw_to_dir = minetest.yaw_to_dir + +--[[ + _ _ +| | | | +| | __ _ _ __ __| | +| | / _` | '_ \ / _` | +| |___| (_| | | | | (_| | +\_____/\__,_|_| |_|\__,_| +]] + + -- move mob in facing direction --this has been modified to be internal --internal = lua (self.yaw) @@ -71,6 +82,22 @@ mobs.jump = function(self, velocity) self.object:add_velocity(vector_new(0,velocity,0)) end + + + + +--[[ + _____ _ +/ ___| (_) +\ `--.__ ___ _ __ ___ + `--. \ \ /\ / / | '_ ` _ \ +/\__/ /\ V V /| | | | | | | +\____/ \_/\_/ |_|_| |_| |_| +]]-- + + + + --make mobs flop mobs.flop = function(self, velocity) @@ -106,7 +133,7 @@ end --this has been modified to be internal --internal = lua (self.yaw) --engine = c++ (self.object:get_yaw()) -mobs.set_fly_velocity = function(self, v) +mobs.set_swim_velocity = function(self, v) local yaw = (self.yaw or 0) local pitch = (self.pitch or 0) diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index f650472fc7..09fa8b1283 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -48,8 +48,7 @@ mobs:register_mob("mobs_mc:squid", { }, visual_size = {x=3, y=3}, makes_footstep_sound = false, - fly = true, - fly_in = { mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source }, + swim = true, breathes_in_water = true, jump = false, view_range = 16, From e8148f81ab7641554096bc03ecda8927d9ad9491 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:36:19 -0400 Subject: [PATCH 064/117] Make underwater mobs try to continuously swim around with quick_rotate_45 --- .../mcl_mobs/api/mob_functions/ai.lua | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 794f8d2f16..9550fcac76 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -13,6 +13,15 @@ local DOUBLE_PI = math.pi * 2 local THIRTY_SECONDTH_PI = DOUBLE_PI * 0.03125 +--a simple helper function which is too small to move into movement.lua +local quick_rotate_45 = function(self,dtime) + self.yaw = self.yaw + THIRTY_SECONDTH_PI + if self.yaw > DOUBLE_PI then + self.yaw = self.yaw - DOUBLE_PI + end +end + + --[[ _ _ | | | | @@ -43,14 +52,6 @@ local cliff_check = function(self,dtime) return free_fall end ---a simple helper function which is too small to move into movement.lua -local quick_rotate_45 = function(self,dtime) - self.yaw = self.yaw + THIRTY_SECONDTH_PI - if self.yaw > DOUBLE_PI then - self.yaw = self.yaw - DOUBLE_PI - end -end - --check if a mob needs to jump local jump_check = function(self,dtime) @@ -101,9 +102,6 @@ end -- states are executed here local land_state_execution = function(self,dtime) - --local yaw = self.object:get_yaw() or 0 - - if self.state == "stand" then --do animation @@ -136,6 +134,7 @@ local land_state_execution = function(self,dtime) local node_in_front_of = jump_check(self) if node_in_front_of == 1 then + mobs.jump(self) --turn if on the edge of cliff @@ -195,7 +194,27 @@ local swim_state_switch = function(self, dtime) end +--check if a mob needs to turn while swimming +local swim_turn_check = function(self,dtime) + + local pos = self.object:get_pos() + pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + + vector_multiply(dir, radius) + + local test_dir = vector.add(pos,dir) + + local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 + + return(green_flag_1) +end + --this is going to need some more logic gates because birds can flop around +--REMOVE THIS - just dump mobs.flop into where this was local flop = function(self,dtime) mobs.flop(self) end @@ -243,11 +262,6 @@ local swim_state_execution = function(self,dtime) --do animation --mobs.set_mob_animation(self, "stand") - --set the velocity of the mob - --mobs.set_velocity(self,0) - - --print("standing") - mobs.set_swim_velocity(self,0) elseif self.state == "swim" then @@ -266,6 +280,13 @@ local swim_state_execution = function(self,dtime) --create a truly random pitch, since there is no easy access to pitch math that I can find self.pitch = math_random() * random_pitch_multiplier[math_random(1,2)] end + + + --do a quick turn to make mob continuously move + --if in a fish tank or something + if swim_turn_check(self,dtime) then + quick_rotate_45(self,dtime) + end mobs.set_swim_velocity(self,self.walk_velocity) @@ -298,10 +319,6 @@ mobs.mob_step = function(self, dtime) return false end - --print(self.object:get_yaw()) - - - --swimming if self.swim then swim_state_switch(self, dtime) From 240d6ea21155f2044d3b728a210811821540013a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:37:04 -0400 Subject: [PATCH 065/117] Add note about quick_rotate_45 actually rotating 11.25 degrees --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 9550fcac76..daf163174e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -14,6 +14,7 @@ local THIRTY_SECONDTH_PI = DOUBLE_PI * 0.03125 --a simple helper function which is too small to move into movement.lua +--this rotates 11.25 degrees, probably should rename it eventually local quick_rotate_45 = function(self,dtime) self.yaw = self.yaw + THIRTY_SECONDTH_PI if self.yaw > DOUBLE_PI then From 07841c89632626f1c3bb4790f8db0c2adddfb2eb Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:38:48 -0400 Subject: [PATCH 066/117] Swap name of quick_rotate_45 to quick_rotate --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index daf163174e..c4e8f32860 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -14,8 +14,7 @@ local THIRTY_SECONDTH_PI = DOUBLE_PI * 0.03125 --a simple helper function which is too small to move into movement.lua ---this rotates 11.25 degrees, probably should rename it eventually -local quick_rotate_45 = function(self,dtime) +local quick_rotate = function(self,dtime) self.yaw = self.yaw + THIRTY_SECONDTH_PI if self.yaw > DOUBLE_PI then self.yaw = self.yaw - DOUBLE_PI @@ -146,7 +145,7 @@ local land_state_execution = function(self,dtime) --function) elseif node_in_front_of == 2 or (self.fear_height ~= 0 and cliff_check(self,dtime)) then --turn 45 degrees if so - quick_rotate_45(self,dtime) + quick_rotate(self,dtime) --stop the mob so it doesn't fall off mobs.set_velocity(self,0) end @@ -286,7 +285,7 @@ local swim_state_execution = function(self,dtime) --do a quick turn to make mob continuously move --if in a fish tank or something if swim_turn_check(self,dtime) then - quick_rotate_45(self,dtime) + quick_rotate(self,dtime) end From f2e909ab8d182febabbdacd9de50a65f27137761 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:41:14 -0400 Subject: [PATCH 067/117] Add in fly logic gate --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index c4e8f32860..41d33e89b0 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -323,6 +323,9 @@ mobs.mob_step = function(self, dtime) if self.swim then swim_state_switch(self, dtime) swim_state_execution(self, dtime) + --flying + elseif self.fly then + print("I probably should be flying >:(") --regular mobs that walk around else land_state_switch(self, dtime) From 8783912938aed1f5566f3e2f5056213f0cefe4a6 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 12:48:57 -0400 Subject: [PATCH 068/117] Add in mobs api swimming animation --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 41d33e89b0..e558716feb 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -213,12 +213,6 @@ local swim_turn_check = function(self,dtime) return(green_flag_1) end ---this is going to need some more logic gates because birds can flop around ---REMOVE THIS - just dump mobs.flop into where this was -local flop = function(self,dtime) - mobs.flop(self) -end - --this is to swap the built in engine acceleration modifier local swim_physics_swapper = function(self,inside_swim_node) @@ -260,7 +254,7 @@ local swim_state_execution = function(self,dtime) if self.state == "stand" then --do animation - --mobs.set_mob_animation(self, "stand") + mobs.set_mob_animation(self, "stand") mobs.set_swim_velocity(self,0) @@ -281,20 +275,23 @@ local swim_state_execution = function(self,dtime) self.pitch = math_random() * random_pitch_multiplier[math_random(1,2)] end + --do animation + mobs.set_mob_animation(self, "walk") --do a quick turn to make mob continuously move --if in a fish tank or something if swim_turn_check(self,dtime) then quick_rotate(self,dtime) end - mobs.set_swim_velocity(self,self.walk_velocity) end --flop around if not inside swim node else - --print("flopping") - flop(self,dtime) + --do animation + mobs.set_mob_animation(self, "stand") + + mobs.flop(self) end end From 0794bc54372c6aaa9c653693da3a18194adf5c95 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 13:04:55 -0400 Subject: [PATCH 069/117] Make flying mobs float in water and lava --- .../mcl_mobs/api/mob_functions/ai.lua | 133 +++++++++++++++++- .../mcl_mobs/api/mob_functions/movement.lua | 70 +++++++++ 2 files changed, 199 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index e558716feb..2cbde73244 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -29,7 +29,7 @@ end | | / _` | '_ \ / _` | | |___| (_| | | | | (_| | \_____/\__,_|_| |_|\__,_| -]] +]]-- --this is basically reverse jump_check local cliff_check = function(self,dtime) @@ -290,13 +290,137 @@ local swim_state_execution = function(self,dtime) else --do animation mobs.set_mob_animation(self, "stand") - + mobs.flop(self) end end +--[[ +______ _ +| ___| | +| |_ | |_ _ +| _| | | | | | +| | | | |_| | +\_| |_|\__, | + __/ | + |___/ +]]-- + +-- state switching logic (stand, walk, run, attacks) +local fly_state_list_wandering = {"stand", "fly"} + +local fly_state_switch = function(self, dtime) + self.state_timer = self.state_timer - dtime + if self.wandering and self.state_timer <= 0 then + self.state_timer = math.random(4,10) + math.random() + self.state = fly_state_list_wandering[math.random(1,#fly_state_list_wandering)] + end +end + + +--check if a mob needs to turn while flyming +local fly_turn_check = function(self,dtime) + + local pos = self.object:get_pos() + pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + + vector_multiply(dir, radius) + + local test_dir = vector.add(pos,dir) + + local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 + + return(green_flag_1) +end + +--this is to swap the built in engine acceleration modifier +local fly_physics_swapper = function(self,inside_fly_node) + + --should be flyming, gravity is applied, switch to floating + if inside_fly_node and self.object:get_acceleration().y ~= 0 then + self.object:set_acceleration(vector_new(0,0,0)) + --not be fly, gravity isn't applied, switch to falling + elseif not inside_fly_node and self.object:get_acceleration().y == 0 then + self.pitch = 0 + self.object:set_acceleration(vector_new(0,-self.gravity,0)) + end +end + + +local random_pitch_multiplier = {-1,1} +-- states are executed here +local fly_state_execution = function(self,dtime) + + local pos = self.object:get_pos() + pos.y = pos.y + self.object:get_properties().collisionbox[5] + local current_node = minetest_get_node(pos).name + local inside_fly_node = minetest_get_item_group(current_node, "solid") == 0 + + --recheck if in water or lava + if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then + inside_fly_node = false + end + + --turn gravity on or off + fly_physics_swapper(self,inside_fly_node) + + --fly properly if inside fly node + if inside_fly_node then + if self.state == "stand" then + + --do animation + mobs.set_mob_animation(self, "stand") + + mobs.set_fly_velocity(self,0) + + elseif self.state == "fly" then + + self.walk_timer = self.walk_timer - dtime + + --reset the walk timer + if self.walk_timer <= 0 then + + --re-randomize the walk timer + self.walk_timer = math.random(1,6) + math.random() + + --set the mob into a random direction + self.yaw = (math_random() * (math.pi * 2)) + + --create a truly random pitch, since there is no easy access to pitch math that I can find + self.pitch = math_random() * random_pitch_multiplier[math_random(1,2)] + end + + --do animation + mobs.set_mob_animation(self, "walk") + + --do a quick turn to make mob continuously move + --if in a bird cage or something + if fly_turn_check(self,dtime) then + quick_rotate(self,dtime) + end + + mobs.set_fly_velocity(self,self.walk_velocity) + end + else + --make the mob float + if self.floats and minetest_get_item_group(current_node, "water") ~= 0 then + mobs.float(self) + end + end +end + + + + + + + --[[ ___ ___ _ _ _ | \/ | (_) | | (_) @@ -306,7 +430,7 @@ ___ ___ _ _ _ \_| |_/\__,_|_|_| |_| \_____/\___/ \__, |_|\___| __/ | |___/ -]] +]]-- --the main loop mobs.mob_step = function(self, dtime) @@ -322,7 +446,8 @@ mobs.mob_step = function(self, dtime) swim_state_execution(self, dtime) --flying elseif self.fly then - print("I probably should be flying >:(") + fly_state_switch(self, dtime) + fly_state_execution(self,dtime) --regular mobs that walk around else land_state_switch(self, dtime) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 0cf6a6ab23..76e0fe7d5d 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -12,6 +12,31 @@ local vector_multiply = vector.multiply local minetest_yaw_to_dir = minetest.yaw_to_dir + +--this is a generic float function +mobs.float = function(self) + + local current_velocity = self.object:get_velocity() + + local goal_velocity = { + x = 0, + y = 5, + z = 0, + } + + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + + new_velocity_addition.x = 0 + new_velocity_addition.z = 0 + + --smooths out mobs a bit + if vector_length(new_velocity_addition) >= 0.0001 then + self.object:add_velocity(new_velocity_addition) + end +end + + + --[[ _ _ | | | | @@ -151,6 +176,51 @@ mobs.set_swim_velocity = function(self, v) } + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + + if vector_length(new_velocity_addition) > vector_length(goal_velocity) then + vector.multiply(new_velocity_addition, (vector_length(goal_velocity) / vector_length(new_velocity_addition))) + end + + --smooths out mobs a bit + if vector_length(new_velocity_addition) >= 0.0001 then + self.object:add_velocity(new_velocity_addition) + end +end + +--[[ +______ _ +| ___| | +| |_ | |_ _ +| _| | | | | | +| | | | |_| | +\_| |_|\__, | + __/ | + |___/ +]]-- + +-- move mob in facing direction +--this has been modified to be internal +--internal = lua (self.yaw) +--engine = c++ (self.object:get_yaw()) +mobs.set_fly_velocity = function(self, v) + + local yaw = (self.yaw or 0) + local pitch = (self.pitch or 0) + + if v == 0 then + pitch = 0 + end + + local current_velocity = self.object:get_velocity() + + local goal_velocity = { + x = (math_sin(yaw) * -v), + y = pitch, + z = (math_cos(yaw) * v), + } + + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) if vector_length(new_velocity_addition) > vector_length(goal_velocity) then From a20f272e08f0170b2761eeba2a12aeaf88efad7b Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 13:05:53 -0400 Subject: [PATCH 070/117] re-adjust logic gate for mobs floating in water and lava --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 2cbde73244..8eae204b36 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -362,9 +362,11 @@ local fly_state_execution = function(self,dtime) local current_node = minetest_get_node(pos).name local inside_fly_node = minetest_get_item_group(current_node, "solid") == 0 + local float_now = false --recheck if in water or lava if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then inside_fly_node = false + float_now = true end --turn gravity on or off @@ -409,7 +411,7 @@ local fly_state_execution = function(self,dtime) end else --make the mob float - if self.floats and minetest_get_item_group(current_node, "water") ~= 0 then + if self.floats and float_now then mobs.float(self) end end From 58d9670e777c3798c676924023375a2579450142 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 13:11:39 -0400 Subject: [PATCH 071/117] Remove collisionbox addition for y position for fly mobs --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 8eae204b36..2c9467278b 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -102,6 +102,18 @@ end -- states are executed here local land_state_execution = function(self,dtime) + local pos = self.object:get_pos() + local collisionbox = self.object:get_properties().collisionbox + --get the center of the mob + pos.y = pos.y + (collisionbox[2] + collisionbox[5] / 2) + local current_node = minetest_get_node(pos).name + local float_now = false + + --recheck if in water or lava + if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then + float_now = true + end + if self.state == "stand" then --do animation @@ -166,6 +178,9 @@ local land_state_execution = function(self,dtime) end + if float_now then + mobs.float(self) + end end @@ -356,9 +371,7 @@ end local random_pitch_multiplier = {-1,1} -- states are executed here local fly_state_execution = function(self,dtime) - local pos = self.object:get_pos() - pos.y = pos.y + self.object:get_properties().collisionbox[5] local current_node = minetest_get_node(pos).name local inside_fly_node = minetest_get_item_group(current_node, "solid") == 0 From d9729fc8651d06566e61bcfcb2e7df0484f25f48 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 13:13:45 -0400 Subject: [PATCH 072/117] Fix parrot's rotation --- mods/ENTITIES/mobs_mc/parrot.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index 5efcb191b4..81d19d5d46 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -24,6 +24,7 @@ mobs:register_mob("mobs_mc:parrot", { mesh = "mobs_mc_parrot.b3d", textures = {{"mobs_mc_parrot_blue.png"},{"mobs_mc_parrot_green.png"},{"mobs_mc_parrot_grey.png"},{"mobs_mc_parrot_red_blue.png"},{"mobs_mc_parrot_yellow_blue.png"}}, visual_size = {x=3, y=3}, + rotate = 270, walk_velocity = 3, run_velocity = 5, sounds = { From 5ade34115cff228994ff3fd680aa15c8225ab6e7 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 13:17:29 -0400 Subject: [PATCH 073/117] Remove random state initialization in set_up.lua --- mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua index 1d48d52f70..1fee55217d 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/set_up.lua @@ -2,8 +2,6 @@ local math_random = math.random local minetest_settings = minetest.settings -local state_randomization = {"stand", "walk"} - -- get entity staticdata mobs.mob_staticdata = function(self) @@ -26,7 +24,6 @@ mobs.mob_staticdata = function(self) self.remove_ok = true self.attack = nil self.following = nil - self.state = state_randomization[math.random(1,#state_randomization)] if use_cmi then self.serialized_cmi_components = cmi.serialize_components(self._cmi_components) From 3cf263d292f9fc5a7a18fafa2aa1fbc8e1840a0a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 16:23:38 -0400 Subject: [PATCH 074/117] Add in dynamic pitch in flying/swimming mobs --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + .../mcl_mobs/api/mob_functions/ai.lua | 16 +++++ .../mcl_mobs/api/mob_functions/animation.lua | 64 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 47804b0d00..1c3ca79b84 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -313,6 +313,7 @@ function mobs:register_mob(name, def) gravity = GRAVITY, swim = def.swim, swim_in = def.swim_in or {mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source}, + pitch_switch = "static", --set_animation = mobs.set_animation, --end j4i stuff diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 2c9467278b..fe7b0309f2 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -1,4 +1,5 @@ local math_random = math.random +local math_pi = math.pi local vector_multiply = vector.multiply local vector_add = vector.add @@ -273,6 +274,8 @@ local swim_state_execution = function(self,dtime) mobs.set_swim_velocity(self,0) + mobs.set_static_pitch(self) + elseif self.state == "swim" then self.walk_timer = self.walk_timer - dtime @@ -300,6 +303,8 @@ local swim_state_execution = function(self,dtime) end mobs.set_swim_velocity(self,self.walk_velocity) + + mobs.set_dynamic_pitch(self) end --flop around if not inside swim node else @@ -307,6 +312,8 @@ local swim_state_execution = function(self,dtime) mobs.set_mob_animation(self, "stand") mobs.flop(self) + + mobs.set_static_pitch(self) end end @@ -394,6 +401,8 @@ local fly_state_execution = function(self,dtime) mobs.set_fly_velocity(self,0) + mobs.set_static_pitch(self) + elseif self.state == "fly" then self.walk_timer = self.walk_timer - dtime @@ -420,12 +429,18 @@ local fly_state_execution = function(self,dtime) quick_rotate(self,dtime) end + mobs.set_dynamic_pitch(self) + mobs.set_fly_velocity(self,self.walk_velocity) end else --make the mob float if self.floats and float_now then + mobs.set_velocity(self, 0) + mobs.float(self) + + mobs.set_static_pitch(self) end end end @@ -476,4 +491,5 @@ mobs.mob_step = function(self, dtime) end self.old_velocity = self.object:get_velocity() + self.old_pos = self.object:get_pos() end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 2f89333dab..8d37b7c090 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -1,4 +1,19 @@ local math_pi = math.pi +local math_floor = math.floor +local HALF_PI = math_pi/2 + + + +local vector_distance = vector.distance +local vector_new = vector.new + +local minetest_dir_to_yaw = minetest.dir_to_yaw + + +-- simple degrees calculation +local degrees = function(yaw) + return(yaw*180.0/math_pi) +end -- set defined animation mobs.set_mob_animation = function(self, anim, fixed_frame) @@ -67,8 +82,8 @@ mobs.death_effect = function(pos, yaw, collisionbox, rotate) time = 0.001, minpos = vector.add(pos, min), maxpos = vector.add(pos, max), - minvel = vector.new(-5,-5,-5), - maxvel = vector.new(5,5,5), + minvel = vector_new(-5,-5,-5), + maxvel = vector_new(5,5,5), minexptime = 1.1, maxexptime = 1.5, minsize = 1, @@ -102,4 +117,49 @@ mobs.movement_rotation_lock = function(self) elseif math.abs(current_engine_yaw - current_lua_yaw) > 0.05 and self.object:get_properties().automatic_face_movement_dir == false then self.object:set_properties{automatic_face_movement_dir = self.rotate} end +end + + +local calculate_pitch = function(self) + local pos = self.object:get_pos() + local pos2 = self.old_pos + + if pos == nil or pos2 == nil then + return false + end + + return(minetest_dir_to_yaw(vector_new(vector_distance(vector_new(pos.x,0,pos.z),vector_new(pos2.x,0,pos2.z)),0,pos.y - pos2.y)) + HALF_PI) +end + +--this is a helper function used to make mobs pitch rotation dynamically flow when flying/swimming +mobs.set_dynamic_pitch = function(self) + local pitch = calculate_pitch(self) + + if not pitch then + return + end + + local current_rotation = self.object:get_rotation() + + current_rotation.x = pitch + + self.object:set_rotation(current_rotation) + + self.pitch_switch = "dynamic" +end + +--this is a helper function used to make mobs pitch rotation reset when flying/swimming +mobs.set_static_pitch = function(self) + + if self.pitch_switch == "static" then + return + end + + local current_rotation = self.object:get_rotation() + + current_rotation.x = 0 + current_rotation.z = 0 + + self.object:set_rotation(current_rotation) + self.pitch_switchfdas = "static" end \ No newline at end of file From e2987245fd6c6ee75383ea92da30e9fc5e10ad1e Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 17:00:34 -0400 Subject: [PATCH 075/117] Balance out collision forces for mobs --- mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua | 6 ------ mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua | 7 ++++++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 8d37b7c090..97d0f7894e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -9,12 +9,6 @@ local vector_new = vector.new local minetest_dir_to_yaw = minetest.dir_to_yaw - --- simple degrees calculation -local degrees = function(yaw) - return(yaw*180.0/math_pi) -end - -- set defined animation mobs.set_mob_animation = function(self, anim, fixed_frame) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua index e6c89e2dbc..91feeb1927 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -1,6 +1,7 @@ local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius local math_random = math.random +local vector_multiply = vector.multiply local integer_test = {-1,1} @@ -74,8 +75,12 @@ mobs.collision = function(self) local vel1 = vector.multiply(velocity, -1.5) local vel2 = vector.multiply(velocity, 1.5) - vel1 = vector.multiply(vel1, force) + vel1 = vector.multiply(vel1, force * 10) vel2 = vector.multiply(vel2, force) + + if object:is_player() then + vel2 = vector_multiply(vel2, 2.5) + end self.object:add_velocity(vel1) object:add_velocity(vel2) From db87b8e0a37cd15ef7931a76d21bbb190a158205 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 17:09:57 -0400 Subject: [PATCH 076/117] fix chicken rotation --- mods/ENTITIES/mobs_mc/chicken.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/chicken.lua b/mods/ENTITIES/mobs_mc/chicken.lua index 246bf216ac..8be3019f6b 100644 --- a/mods/ENTITIES/mobs_mc/chicken.lua +++ b/mods/ENTITIES/mobs_mc/chicken.lua @@ -25,7 +25,7 @@ mobs:register_mob("mobs_mc:chicken", { {"mobs_mc_chicken.png"}, }, visual_size = {x=2.2, y=2.2}, - + rotate = 270, makes_footstep_sound = true, walk_velocity = 1, drops = { From 719bb2a3c96ca020f8f828959e377831f47cd27b Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sat, 17 Apr 2021 18:21:33 -0400 Subject: [PATCH 077/117] Add in prototype jump-only mobs api --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 +- .../mcl_mobs/api/mob_functions/ai.lua | 115 +++++++++++++++++- .../mcl_mobs/api/mob_functions/movement.lua | 48 ++++++++ mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 6 +- 4 files changed, 167 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 1c3ca79b84..79a47a78c5 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -314,7 +314,7 @@ function mobs:register_mob(name, def) swim = def.swim, swim_in = def.swim_in or {mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source}, pitch_switch = "static", - --set_animation = mobs.set_animation, + jump_only = def.jump_only, --end j4i stuff -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index fe7b0309f2..ce3e468b3c 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -342,7 +342,7 @@ local fly_state_switch = function(self, dtime) end ---check if a mob needs to turn while flyming +--check if a mob needs to turn while flying local fly_turn_check = function(self,dtime) local pos = self.object:get_pos() @@ -446,8 +446,115 @@ local fly_state_execution = function(self,dtime) end +--[[ + ___ + |_ | + | |_ _ _ __ ___ _ __ + | | | | | '_ ` _ \| '_ \ +/\__/ / |_| | | | | | | |_) | +\____/ \__,_|_| |_| |_| .__/ + | | + |_| +]]-- +--check if a mob needs to turn while jumping +local jump_turn_check = function(self,dtime) + + local pos = self.object:get_pos() + pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + + vector_multiply(dir, radius) + + local test_dir = vector.add(pos,dir) + + local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 + + return(green_flag_1) +end + +-- state switching logic (stand, jump, run, attacks) +local jump_state_list_wandering = {"stand", "jump"} + +local jump_state_switch = function(self, dtime) + self.state_timer = self.state_timer - dtime + if self.wandering and self.state_timer <= 0 then + self.state_timer = math.random(4,10) + math.random() + self.state = jump_state_list_wandering[math.random(1,#jump_state_list_wandering)] + end +end + +-- states are executed here +local jump_state_execution = function(self,dtime) + + local pos = self.object:get_pos() + local collisionbox = self.object:get_properties().collisionbox + --get the center of the mob + pos.y = pos.y + (collisionbox[2] + collisionbox[5] / 2) + local current_node = minetest_get_node(pos).name + + local float_now = false + + --recheck if in water or lava + if minetest_get_item_group(current_node, "water") ~= 0 or minetest_get_item_group(current_node, "lava") ~= 0 then + float_now = true + end + + if self.state == "stand" then + + --do animation + mobs.set_mob_animation(self, "stand") + + --set the velocity of the mob + mobs.set_velocity(self,0) + + elseif self.state == "jump" then + + self.walk_timer = self.walk_timer - dtime + + --reset the jump timer + if self.walk_timer <= 0 then + + --re-randomize the jump timer + self.walk_timer = math.random(1,6) + math.random() + + --set the mob into a random direction + self.yaw = (math_random() * (math.pi * 2)) + end + + --do animation + mobs.set_mob_animation(self, "walk") + + --enable rotation locking + mobs.movement_rotation_lock(self) + + --jumping mobs are more loosey goosey + if node_in_front_of == 1 then + quick_rotate(self,dtime) + end + + --only move forward if path is clear + mobs.jump_move(self,self.walk_velocity) + + elseif self.state == "run" then + + print("run") + + elseif self.state == "attack" then + + print("attack") + + end + + if float_now then + mobs.float(self) + end +end + @@ -470,8 +577,12 @@ mobs.mob_step = function(self, dtime) return false end + --jump only (like slimes) + if self.jump_only then + jump_state_switch(self, dtime) + jump_state_execution(self, dtime) --swimming - if self.swim then + elseif self.swim then swim_state_switch(self, dtime) swim_state_execution(self, dtime) --flying diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 76e0fe7d5d..1ff7809512 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -221,6 +221,54 @@ mobs.set_fly_velocity = function(self, v) } + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) + + if vector_length(new_velocity_addition) > vector_length(goal_velocity) then + vector.multiply(new_velocity_addition, (vector_length(goal_velocity) / vector_length(new_velocity_addition))) + end + + --smooths out mobs a bit + if vector_length(new_velocity_addition) >= 0.0001 then + self.object:add_velocity(new_velocity_addition) + end +end + + +--[[ + ___ + |_ | + | |_ _ _ __ ___ _ __ + | | | | | '_ ` _ \| '_ \ +/\__/ / |_| | | | | | | |_) | +\____/ \__,_|_| |_| |_| .__/ + | | + |_| +]]-- + +--special mob jump movement +mobs.jump_move = function(self, velocity) + + if self.object:get_velocity().y ~= 0 or not self.old_velocity or (self.old_velocity and self.old_velocity.y > 0) then + return + end + + --make the mob stick for a split second + mobs.set_velocity(self,0) + + --fallback velocity to allow modularity + jump_height = 8 + + local yaw = (self.yaw or 0) + + local current_velocity = self.object:get_velocity() + + local goal_velocity = { + x = (math_sin(yaw) * -velocity), + y = jump_height, + z = (math_cos(yaw) * velocity), + } + + local new_velocity_addition = vector.subtract(goal_velocity,current_velocity) if vector_length(new_velocity_addition) > vector_length(goal_velocity) then diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 6c8000a50d..1926ce89df 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -64,6 +64,7 @@ local slime_big = { hp_max = 16, xp_min = 4, xp_max = 4, + rotate = 270, collisionbox = {-1.02, -0.01, -1.02, 1.02, 2.03, 1.02}, visual_size = {x=12.5, y=12.5}, textures = {{"mobs_mc_slime.png"}}, @@ -100,6 +101,7 @@ local slime_big = { view_range = 16, attack_type = "dogfight", passive = false, + jump_only = true, jump = true, walk_velocity = 2.5, run_velocity = 2.5, @@ -311,6 +313,7 @@ local magma_cube_big = { }, walk_velocity = 4, run_velocity = 4, + rotate = 270, damage = 6, reach = 3, armor = 53, @@ -337,12 +340,13 @@ local magma_cube_big = { }, water_damage = 0, lava_damage = 0, - fire_damage = 0, + fire_damage = 0, light_damage = 0, fall_damage = 0, view_range = 16, attack_type = "dogfight", passive = false, + jump_only = true, jump = true, jump_height = 8, walk_chance = 0, From 1920ddf91530a7c033c8288cd3a752f3ee7ba850 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 18 Apr 2021 21:02:03 -0400 Subject: [PATCH 078/117] Change all enemy attack info to more workable and understandable attacks --- mods/ENTITIES/mobs_mc/blaze.lua | 2 +- mods/ENTITIES/mobs_mc/ender_dragon.lua | 2 +- mods/ENTITIES/mobs_mc/endermite.lua | 1 + mods/ENTITIES/mobs_mc/ghast.lua | 2 +- mods/ENTITIES/mobs_mc/guardian.lua | 2 +- mods/ENTITIES/mobs_mc/guardian_elder.lua | 2 +- mods/ENTITIES/mobs_mc/polar_bear.lua | 2 +- mods/ENTITIES/mobs_mc/shulker.lua | 2 +- mods/ENTITIES/mobs_mc/silverfish.lua | 2 +- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 2 +- mods/ENTITIES/mobs_mc/skeleton_wither.lua | 2 +- mods/ENTITIES/mobs_mc/slime+magma_cube.lua | 4 ++-- mods/ENTITIES/mobs_mc/spider.lua | 2 +- mods/ENTITIES/mobs_mc/vex.lua | 2 +- mods/ENTITIES/mobs_mc/villager_evoker.lua | 2 +- mods/ENTITIES/mobs_mc/villager_illusioner.lua | 2 +- mods/ENTITIES/mobs_mc/villager_vindicator.lua | 2 +- mods/ENTITIES/mobs_mc/villager_zombie.lua | 2 +- mods/ENTITIES/mobs_mc/witch.lua | 2 +- mods/ENTITIES/mobs_mc/wither.lua | 2 +- mods/ENTITIES/mobs_mc/zombie.lua | 2 +- mods/ENTITIES/mobs_mc/zombiepig.lua | 2 +- 22 files changed, 23 insertions(+), 22 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 847e2f4a53..d7e0a5c48f 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -63,7 +63,7 @@ mobs:register_mob("mobs_mc:blaze", { fall_speed = -2.25, light_damage = 0, view_range = 16, - attack_type = "dogshoot", + attack_type = "projectile", arrow = "mobs_mc:blaze_fireball", shoot_interval = 3.5, shoot_offset = 1.0, diff --git a/mods/ENTITIES/mobs_mc/ender_dragon.lua b/mods/ENTITIES/mobs_mc/ender_dragon.lua index a6f4042754..ec31be35c3 100644 --- a/mods/ENTITIES/mobs_mc/ender_dragon.lua +++ b/mods/ENTITIES/mobs_mc/ender_dragon.lua @@ -46,7 +46,7 @@ mobs:register_mob("mobs_mc:enderdragon", { lava_damage = 0, fire_damage = 0, on_rightclick = nil, - attack_type = "dogshoot", + attack_type = "projectile", arrow = "mobs_mc:dragon_fireball", shoot_interval = 0.5, shoot_offset = -1.0, diff --git a/mods/ENTITIES/mobs_mc/endermite.lua b/mods/ENTITIES/mobs_mc/endermite.lua index da3922a106..e413f65b30 100644 --- a/mods/ENTITIES/mobs_mc/endermite.lua +++ b/mods/ENTITIES/mobs_mc/endermite.lua @@ -14,6 +14,7 @@ mobs:register_mob("mobs_mc:endermite", { xp_max = 3, armor = {fleshy = 100, arthropod = 100}, group_attack = true, + attack_type = "punch", collisionbox = {-0.2, -0.01, -0.2, 0.2, 0.29, 0.2}, visual = "mesh", mesh = "mobs_mc_endermite.b3d", diff --git a/mods/ENTITIES/mobs_mc/ghast.lua b/mods/ENTITIES/mobs_mc/ghast.lua index 83a10bfc40..8a800b7882 100644 --- a/mods/ENTITIES/mobs_mc/ghast.lua +++ b/mods/ENTITIES/mobs_mc/ghast.lua @@ -49,7 +49,7 @@ mobs:register_mob("mobs_mc:ghast", { }, fall_damage = 0, view_range = 100, - attack_type = "dogshoot", + attack_type = "projectile", arrow = "mobs_mc:fireball", shoot_interval = 3.5, shoot_offset = -5, diff --git a/mods/ENTITIES/mobs_mc/guardian.lua b/mods/ENTITIES/mobs_mc/guardian.lua index 13c857ea39..086338da82 100644 --- a/mods/ENTITIES/mobs_mc/guardian.lua +++ b/mods/ENTITIES/mobs_mc/guardian.lua @@ -13,7 +13,7 @@ mobs:register_mob("mobs_mc:guardian", { xp_max = 10, breath_max = -1, passive = false, - attack_type = "dogfight", + attack_type = "punch", pathfinding = 1, view_range = 16, walk_velocity = 2, diff --git a/mods/ENTITIES/mobs_mc/guardian_elder.lua b/mods/ENTITIES/mobs_mc/guardian_elder.lua index 089f6e38f7..087e85353a 100644 --- a/mods/ENTITIES/mobs_mc/guardian_elder.lua +++ b/mods/ENTITIES/mobs_mc/guardian_elder.lua @@ -15,7 +15,7 @@ mobs:register_mob("mobs_mc:guardian_elder", { xp_max = 10, breath_max = -1, passive = false, - attack_type = "dogfight", + attack_type = "punch", pathfinding = 1, view_range = 16, walk_velocity = 2, diff --git a/mods/ENTITIES/mobs_mc/polar_bear.lua b/mods/ENTITIES/mobs_mc/polar_bear.lua index 5d2853f6d2..f1772be997 100644 --- a/mods/ENTITIES/mobs_mc/polar_bear.lua +++ b/mods/ENTITIES/mobs_mc/polar_bear.lua @@ -30,7 +30,7 @@ mobs:register_mob("mobs_mc:polar_bear", { walk_velocity = 1.2, run_velocity = 2.4, group_attack = true, - attack_type = "dogfight", + attack_type = "punch", drops = { -- 3/4 chance to drop raw fish (poor approximation) {name = mobs_mc.items.fish_raw, diff --git a/mods/ENTITIES/mobs_mc/shulker.lua b/mods/ENTITIES/mobs_mc/shulker.lua index 8000d0937b..b6a4a61991 100644 --- a/mods/ENTITIES/mobs_mc/shulker.lua +++ b/mods/ENTITIES/mobs_mc/shulker.lua @@ -14,7 +14,7 @@ local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:shulker", { type = "monster", spawn_class = "hostile", - attack_type = "shoot", + attack_type = "projectile", shoot_interval = 0.5, arrow = "mobs_mc:shulkerbullet", shoot_offset = 0.5, diff --git a/mods/ENTITIES/mobs_mc/silverfish.lua b/mods/ENTITIES/mobs_mc/silverfish.lua index 433211503b..6ed9e6dca7 100644 --- a/mods/ENTITIES/mobs_mc/silverfish.lua +++ b/mods/ENTITIES/mobs_mc/silverfish.lua @@ -43,7 +43,7 @@ mobs:register_mob("mobs_mc:silverfish", { run_start = 0, run_end = 20, }, view_range = 16, - attack_type = "dogfight", + attack_type = "punch", damage = 1, reach = 1, }) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index b43873b2aa..da3df4664b 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -84,7 +84,7 @@ local skeleton = { ignited_by_sunlight = true, view_range = 16, fear_height = 4, - attack_type = "dogshoot", + attack_type = "projectile", arrow = "mcl_bows:arrow_entity", shoot_arrow = function(self, pos, dir) if mod_bows then diff --git a/mods/ENTITIES/mobs_mc/skeleton_wither.lua b/mods/ENTITIES/mobs_mc/skeleton_wither.lua index da472d6057..c539e476b8 100644 --- a/mods/ENTITIES/mobs_mc/skeleton_wither.lua +++ b/mods/ENTITIES/mobs_mc/skeleton_wither.lua @@ -85,7 +85,7 @@ mobs:register_mob("mobs_mc:witherskeleton", { fire_damage = 0, light_damage = 0, view_range = 16, - attack_type = "dogfight", + attack_type = "punch", dogshoot_switch = 1, dogshoot_count_max =0.5, fear_height = 4, diff --git a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua index 1926ce89df..b29ccd454a 100644 --- a/mods/ENTITIES/mobs_mc/slime+magma_cube.lua +++ b/mods/ENTITIES/mobs_mc/slime+magma_cube.lua @@ -99,7 +99,7 @@ local slime_big = { }, fall_damage = 0, view_range = 16, - attack_type = "dogfight", + attack_type = "jump_punch", passive = false, jump_only = true, jump = true, @@ -344,7 +344,7 @@ local magma_cube_big = { light_damage = 0, fall_damage = 0, view_range = 16, - attack_type = "dogfight", + attack_type = "jump_punch", passive = false, jump_only = true, jump = true, diff --git a/mods/ENTITIES/mobs_mc/spider.lua b/mods/ENTITIES/mobs_mc/spider.lua index bb5e29eb1f..95179310b6 100644 --- a/mods/ENTITIES/mobs_mc/spider.lua +++ b/mods/ENTITIES/mobs_mc/spider.lua @@ -17,7 +17,7 @@ local spider = { spawn_class = "hostile", passive = false, docile_by_day = true, - attack_type = "dogfight", + attack_type = "punch", pathfinding = 1, damage = 2, reach = 2, diff --git a/mods/ENTITIES/mobs_mc/vex.lua b/mods/ENTITIES/mobs_mc/vex.lua index cccdebe7a5..c2ce2a87a6 100644 --- a/mods/ENTITIES/mobs_mc/vex.lua +++ b/mods/ENTITIES/mobs_mc/vex.lua @@ -14,7 +14,7 @@ mobs:register_mob("mobs_mc:vex", { spawn_class = "hostile", pathfinding = 1, passive = false, - attack_type = "dogfight", + attack_type = "punch", physical = false, hp_min = 14, hp_max = 14, diff --git a/mods/ENTITIES/mobs_mc/villager_evoker.lua b/mods/ENTITIES/mobs_mc/villager_evoker.lua index abe0e9ca2b..86338eb143 100644 --- a/mods/ENTITIES/mobs_mc/villager_evoker.lua +++ b/mods/ENTITIES/mobs_mc/villager_evoker.lua @@ -34,7 +34,7 @@ mobs:register_mob("mobs_mc:evoker", { walk_velocity = 0.2, run_velocity = 1.4, group_attack = true, - attack_type = "dogfight", + attack_type = "punch", -- Summon vexes custom_attack = function(self, to_attack) local r = pr:next(2,4) diff --git a/mods/ENTITIES/mobs_mc/villager_illusioner.lua b/mods/ENTITIES/mobs_mc/villager_illusioner.lua index 0bbe2a5f6d..e4642c847c 100644 --- a/mods/ENTITIES/mobs_mc/villager_illusioner.lua +++ b/mods/ENTITIES/mobs_mc/villager_illusioner.lua @@ -9,7 +9,7 @@ local mod_bows = minetest.get_modpath("mcl_bows") ~= nil mobs:register_mob("mobs_mc:illusioner", { type = "monster", spawn_class = "hostile", - attack_type = "shoot", + attack_type = "projectile", shoot_interval = 2.5, shoot_offset = 1.5, arrow = "mcl_bows:arrow_entity", diff --git a/mods/ENTITIES/mobs_mc/villager_vindicator.lua b/mods/ENTITIES/mobs_mc/villager_vindicator.lua index 56b295066b..19b2c7a7f6 100644 --- a/mods/ENTITIES/mobs_mc/villager_vindicator.lua +++ b/mods/ENTITIES/mobs_mc/villager_vindicator.lua @@ -36,7 +36,7 @@ mobs:register_mob("mobs_mc:vindicator", { reach = 2, walk_velocity = 1.2, run_velocity = 2.4, - attack_type = "dogfight", + attack_type = "punch", drops = { {name = mobs_mc.items.emerald, chance = 1, diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index 325cf5955b..f6eff6e0ab 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -51,7 +51,7 @@ mobs:register_mob("mobs_mc:villager_zombie", { reach = 2, walk_velocity = 1.2, run_velocity = 2.4, - attack_type = "dogfight", + attack_type = "punch", group_attack = true, drops = { {name = mobs_mc.items.rotten_flesh, diff --git a/mods/ENTITIES/mobs_mc/witch.lua b/mods/ENTITIES/mobs_mc/witch.lua index f9f9b8d1f0..83174313fb 100644 --- a/mods/ENTITIES/mobs_mc/witch.lua +++ b/mods/ENTITIES/mobs_mc/witch.lua @@ -33,7 +33,7 @@ mobs:register_mob("mobs_mc:witch", { run_velocity = 2.4, pathfinding = 1, group_attack = true, - attack_type = "dogshoot", + attack_type = "projectile", arrow = "mobs_mc:potion_arrow", shoot_interval = 2.5, shoot_offset = 1, diff --git a/mods/ENTITIES/mobs_mc/wither.lua b/mods/ENTITIES/mobs_mc/wither.lua index 2d53cc547f..6a63b2f821 100644 --- a/mods/ENTITIES/mobs_mc/wither.lua +++ b/mods/ENTITIES/mobs_mc/wither.lua @@ -52,7 +52,7 @@ mobs:register_mob("mobs_mc:wither", { }, lava_damage = 0, fire_damage = 0, - attack_type = "dogshoot", + attack_type = "projectile", explosion_strength = 8, dogshoot_stop = true, arrow = "mobs_mc:wither_skull", diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index fed83f233a..4d88b25772 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -88,7 +88,7 @@ local zombie = { ignited_by_sunlight = true, sunlight_damage = 2, view_range = 16, - attack_type = "dogfight", + attack_type = "punch", harmed_by_heal = true, } diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index ebd8ce4856..efaf1b3967 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -20,7 +20,7 @@ local pigman = { xp_min = 6, xp_max = 6, armor = {undead = 90, fleshy = 90}, - attack_type = "dogfight", + attack_type = "punch", group_attack = { "mobs_mc:pigman", "mobs_mc:baby_pigman" }, damage = 9, reach = 2, From 39985aa558d9f43a6a2e82fb6d59ad0ca8b6324d Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 18 Apr 2021 21:22:21 -0400 Subject: [PATCH 079/117] Up fallback max xp to 3 --- mods/ENTITIES/mcl_mobs/api/api.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 79a47a78c5..67865da6eb 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -58,7 +58,7 @@ local DEATH_DELAY = 0.5 local DEFAULT_FALL_SPEED = -10 local FLOP_HEIGHT = 5.0 local FLOP_HOR_SPEED = 1.5 -local GRAVITY = minetest_settings:get("movement_gravity") + 9.81 +local GRAVITY = minetest_settings:get("movement_gravity")-- + 9.81 local MOB_CAP = {} @@ -215,7 +215,7 @@ function mobs:register_mob(name, def) hp_min = scale_difficulty(def.hp_min, 5, 1), hp_max = scale_difficulty(def.hp_max, 10, 1), xp_min = def.xp_min or 0, - xp_max = def.xp_max or 0, + xp_max = def.xp_max or 3, xp_timestamp = 0, breath_max = def.breath_max or 15, breathes_in_water = def.breathes_in_water or false, @@ -298,7 +298,10 @@ function mobs:register_mob(name, def) runaway_from = def.runaway_from, owner_loyal = def.owner_loyal, facing_fence = false, + + _cmi_is_mob = true, + pushable = def.pushable or true, --j4i stuff From 4d589dfb2aa10cb664b4d3b3471960e6d648b92c Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 18 Apr 2021 21:22:39 -0400 Subject: [PATCH 080/117] Remove literally unneeded mobs:capture_mob --- mods/ENTITIES/extra_mobs/strider.lua | 3 --- mods/ENTITIES/mcl_mobs/api.txt | 17 ----------------- .../api/mob_functions/backup_code_api.lua | 7 ------- .../mcl_mobs/api/mob_functions/interaction.lua | 9 +++++---- .../mcl_mobs/api/mob_functions/movement.lua | 11 +++++++---- mods/ENTITIES/mobs_mc/chicken.lua | 1 - mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 4 +--- mods/ENTITIES/mobs_mc/horse.lua | 5 +---- mods/ENTITIES/mobs_mc/llama.lua | 5 +---- mods/ENTITIES/mobs_mc/ocelot.lua | 1 - mods/ENTITIES/mobs_mc/parrot.lua | 1 - mods/ENTITIES/mobs_mc/pig.lua | 4 ---- mods/ENTITIES/mobs_mc/rabbit.lua | 1 - mods/ENTITIES/mobs_mc/sheep.lua | 1 - mods/ENTITIES/mobs_mc/wolf.lua | 2 -- 15 files changed, 15 insertions(+), 57 deletions(-) diff --git a/mods/ENTITIES/extra_mobs/strider.lua b/mods/ENTITIES/extra_mobs/strider.lua index 1847161565..6796bdca21 100644 --- a/mods/ENTITIES/extra_mobs/strider.lua +++ b/mods/ENTITIES/extra_mobs/strider.lua @@ -190,9 +190,6 @@ local strider = { inv:set_stack("main",self.driver:get_wield_index(), wielditem) end return - - elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then - mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end end, } diff --git a/mods/ENTITIES/mcl_mobs/api.txt b/mods/ENTITIES/mcl_mobs/api.txt index eda74aeb42..0e4810b0fd 100644 --- a/mods/ENTITIES/mcl_mobs/api.txt +++ b/mods/ENTITIES/mcl_mobs/api.txt @@ -502,20 +502,6 @@ and damages any entity caught inside the blast radius. Protection will limit node destruction but not entity damage. -mobs:capture_mob ----------------- - -mobs:capture_mob(...) - -Does nothing and returns false. - -This function is provided for compability with Mobs Redo for an attempt to -capture a mob. -Mobs cannot be captured in MineClone 2. - -In Mobs Redo, this is generally called inside the on_rightclick section of the mob -api code, it provides a chance of capturing the mob. See Mobs Redo documentation -of parameters. Feeding and Taming/Breeding --------------------------- @@ -781,8 +767,5 @@ mobs:register_mob("mob_horse:horse", { inv:remove_item("main", "mobs:saddle") end end - - -- used to capture horse with magic lasso - mobs:capture_mob(self, clicker, 0, 0, 80, false, nil) end }) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua index 292a27ec0d..d7b2291479 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua @@ -112,13 +112,6 @@ function mobs:spawn_child(pos, mob_type) end --- No-op in MCL2 (capturing mobs is not possible). --- Provided for compability with Mobs Redo -function mobs:capture_mob(self, clicker, chance_hand, chance_net, chance_lasso, force_take, replacewith) - return false -end - - -- No-op in MCL2 (protecting mobs is not possible). function mobs:protect(self, clicker) return false diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua index b996867cf8..490ae85182 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -1,5 +1,10 @@ +mobs.feed_tame = function(self) + return nil +end + -- Code to execute before custom on_rightclick handling local on_rightclick_prefix = function(self, clicker) + local item = clicker:get_wielded_item() -- Name mob with nametag @@ -32,8 +37,4 @@ mobs.create_mob_on_rightclick = function(on_rightclick) on_rightclick(self, clicker) end end -end - -mobs.feed_tame = function(self) - return nil end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index 1ff7809512..f983734ebe 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -11,6 +11,9 @@ local vector_multiply = vector.multiply local minetest_yaw_to_dir = minetest.yaw_to_dir +local DEFAULT_JUMP_HEIGHT = 5 +local DEFAULT_FLOAT_SPEED = 4 + --this is a generic float function @@ -20,7 +23,7 @@ mobs.float = function(self) local goal_velocity = { x = 0, - y = 5, + y = DEFAULT_FLOAT_SPEED, z = 0, } @@ -102,7 +105,7 @@ mobs.jump = function(self, velocity) end --fallback velocity to allow modularity - velocity = velocity or 8 + velocity = velocity or DEFAULT_JUMP_HEIGHT self.object:add_velocity(vector_new(0,velocity,0)) end @@ -133,7 +136,7 @@ mobs.flop = function(self, velocity) mobs.set_velocity(self, 0) --fallback velocity to allow modularity - velocity = velocity or 8 + velocity = velocity or DEFAULT_JUMP_HEIGHT --create a random direction (2d yaw) local dir = DOUBLE_PI * math_random() @@ -256,7 +259,7 @@ mobs.jump_move = function(self, velocity) mobs.set_velocity(self,0) --fallback velocity to allow modularity - jump_height = 8 + jump_height = DEFAULT_JUMP_HEIGHT local yaw = (self.yaw or 0) diff --git a/mods/ENTITIES/mobs_mc/chicken.lua b/mods/ENTITIES/mobs_mc/chicken.lua index 8be3019f6b..3d7ba8606e 100644 --- a/mods/ENTITIES/mobs_mc/chicken.lua +++ b/mods/ENTITIES/mobs_mc/chicken.lua @@ -70,7 +70,6 @@ mobs:register_mob("mobs_mc:chicken", { on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, true) then return end if mobs:protect(self, clicker) then return end - if mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end end, do_custom = function(self, dtime) diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index be4cceea37..9ad7b2a182 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -71,7 +71,6 @@ local cow_def = { end return end - mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end, follow = mobs_mc.items.wheat, view_range = 10, @@ -139,8 +138,7 @@ mooshroom_def.on_rightclick = function(self, clicker) pos.y = pos.y + 0.5 minetest.add_item(pos, {name = mobs_mc.items.mushroom_stew}) end - end - mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) + end end mobs:register_mob("mobs_mc:mooshroom", mooshroom_def) diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index 938a6b6ace..b9d79a0752 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -355,10 +355,7 @@ local horse = { self.object:set_properties({stepheight = 1.1}) mobs.attach(self, clicker) - - -- Used to capture horse - elseif not self.driver and iname ~= "" then - mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) + end end end, diff --git a/mods/ENTITIES/mobs_mc/llama.lua b/mods/ENTITIES/mobs_mc/llama.lua index 8ff82b502a..5951f9dffb 100644 --- a/mods/ENTITIES/mobs_mc/llama.lua +++ b/mods/ENTITIES/mobs_mc/llama.lua @@ -182,10 +182,7 @@ mobs:register_mob("mobs_mc:llama", { self.object:set_properties({stepheight = 1.1}) mobs.attach(self, clicker) end - - -- Used to capture llama - elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then - mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) + end end, diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index f3c8c87ae1..139b687853 100644 --- a/mods/ENTITIES/mobs_mc/ocelot.lua +++ b/mods/ENTITIES/mobs_mc/ocelot.lua @@ -121,7 +121,6 @@ cat.sounds = { } cat.on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, false) then return end - if mobs:capture_mob(self, clicker, 0, 60, 5, false, nil) then return end if mobs:protect(self, clicker) then return end if self.child then return end diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index 81d19d5d46..06a2dc18ba 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -86,7 +86,6 @@ mobs:register_mob("mobs_mc:parrot", { -- Feed to tame, but not breed if mobs:feed_tame(self, clicker, 1, false, true) then return end if mobs:protect(self, clicker) then return end - if mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end end, }) diff --git a/mods/ENTITIES/mobs_mc/pig.lua b/mods/ENTITIES/mobs_mc/pig.lua index b7cdf1afe9..da7e686ada 100644 --- a/mods/ENTITIES/mobs_mc/pig.lua +++ b/mods/ENTITIES/mobs_mc/pig.lua @@ -163,10 +163,6 @@ mobs:register_mob("mobs_mc:pig", { inv:set_stack("main",self.driver:get_wield_index(), wielditem) end return - - -- Capture pig - elseif not self.driver and clicker:get_wielded_item():get_name() ~= "" then - mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) end end, diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 74bdffcd80..0f67bb7d7c 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -62,7 +62,6 @@ local rabbit = { -- Feed, tame protect or capture if mobs:feed_tame(self, clicker, 1, true, true) then return end if mobs:protect(self, clicker) then return end - if mobs:capture_mob(self, clicker, 0, 50, 80, false, nil) then return end end, do_custom = function(self) -- Easter egg: Change texture if rabbit is named “Toast” diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index d82df8cf9d..8ba8aecd8f 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -251,7 +251,6 @@ mobs:register_mob("mobs_mc:sheep", { end return end - if mobs:capture_mob(self, clicker, 0, 5, 70, false, nil) then return end end, on_breed = function(parent1, parent2) -- Breed sheep and choose a fur color for the child. diff --git a/mods/ENTITIES/mobs_mc/wolf.lua b/mods/ENTITIES/mobs_mc/wolf.lua index b1c077d465..319a4f9594 100644 --- a/mods/ENTITIES/mobs_mc/wolf.lua +++ b/mods/ENTITIES/mobs_mc/wolf.lua @@ -149,8 +149,6 @@ dog.on_rightclick = function(self, clicker) if mobs:protect(self, clicker) then return - elseif item:get_name() ~= "" and mobs:capture_mob(self, clicker, 0, 2, 80, false, nil) then - return elseif is_food(item:get_name()) then -- Feed to increase health local hp = self.health From 85e531bf106df326b2ca470b5a94aeb06f92d4d6 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Sun, 18 Apr 2021 21:24:31 -0400 Subject: [PATCH 081/117] Remove unneeded mobs:protect from code --- mods/ENTITIES/extra_mobs/strider.lua | 1 - mods/ENTITIES/mcl_mobs/api.txt | 13 ------------- .../mcl_mobs/api/mob_functions/backup_code_api.lua | 5 ----- mods/ENTITIES/mobs_mc/chicken.lua | 1 - mods/ENTITIES/mobs_mc/cow+mooshroom.lua | 2 -- mods/ENTITIES/mobs_mc/horse.lua | 6 +----- mods/ENTITIES/mobs_mc/llama.lua | 3 +-- mods/ENTITIES/mobs_mc/ocelot.lua | 1 - mods/ENTITIES/mobs_mc/parrot.lua | 1 - mods/ENTITIES/mobs_mc/pig.lua | 1 - mods/ENTITIES/mobs_mc/rabbit.lua | 1 - mods/ENTITIES/mobs_mc/sheep.lua | 1 - mods/ENTITIES/mobs_mc/wolf.lua | 4 +--- 13 files changed, 3 insertions(+), 37 deletions(-) diff --git a/mods/ENTITIES/extra_mobs/strider.lua b/mods/ENTITIES/extra_mobs/strider.lua index 6796bdca21..d6c8542077 100644 --- a/mods/ENTITIES/extra_mobs/strider.lua +++ b/mods/ENTITIES/extra_mobs/strider.lua @@ -124,7 +124,6 @@ local strider = { if wielditem:get_name() ~= controlitem then if mobs:feed_tame(self, clicker, 1, true, true) then return end end - if mobs:protect(self, clicker) then return end if self.child then return diff --git a/mods/ENTITIES/mcl_mobs/api.txt b/mods/ENTITIES/mcl_mobs/api.txt index 0e4810b0fd..5d49ca7efa 100644 --- a/mods/ENTITIES/mcl_mobs/api.txt +++ b/mods/ENTITIES/mcl_mobs/api.txt @@ -521,19 +521,6 @@ Will return true when mob is fed with item it likes. them up -Protecting Mobs ---------------- - -mobs:protect(self, clicker) - -This function can be used to right-click any tamed mob with mobs:protector item, -this will protect the mob from harm inside of a protected area from other -players. Will return true when mob right-clicked with mobs:protector item. - - 'self' mob information - 'clicker' player information - - Riding Mobs ----------- diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua index d7b2291479..2c1ba19832 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua @@ -112,11 +112,6 @@ function mobs:spawn_child(pos, mob_type) end --- No-op in MCL2 (protecting mobs is not possible). -function mobs:protect(self, clicker) - return false -end - -- feeding, taming and breeding (thanks blert2112) function mobs:feed_tame(self, clicker, feed_count, breed, tame) diff --git a/mods/ENTITIES/mobs_mc/chicken.lua b/mods/ENTITIES/mobs_mc/chicken.lua index 3d7ba8606e..2fe82293e3 100644 --- a/mods/ENTITIES/mobs_mc/chicken.lua +++ b/mods/ENTITIES/mobs_mc/chicken.lua @@ -69,7 +69,6 @@ mobs:register_mob("mobs_mc:chicken", { on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, true) then return end - if mobs:protect(self, clicker) then return end end, do_custom = function(self, dtime) diff --git a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua index 9ad7b2a182..59b80ecb92 100644 --- a/mods/ENTITIES/mobs_mc/cow+mooshroom.lua +++ b/mods/ENTITIES/mobs_mc/cow+mooshroom.lua @@ -50,7 +50,6 @@ local cow_def = { follow = mobs_mc.follow.cow, on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, true) then return end - if mobs:protect(self, clicker) then return end if self.child then return @@ -86,7 +85,6 @@ mooshroom_def.mesh = "mobs_mc_cow.b3d" mooshroom_def.textures = { {"mobs_mc_mooshroom.png", "mobs_mc_mushroom_red.png"}, {"mobs_mc_mooshroom_brown.png", "mobs_mc_mushroom_brown.png" } } mooshroom_def.on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, true) then return end - if mobs:protect(self, clicker) then return end if self.child then return diff --git a/mods/ENTITIES/mobs_mc/horse.lua b/mods/ENTITIES/mobs_mc/horse.lua index b9d79a0752..0e0246d4e4 100644 --- a/mods/ENTITIES/mobs_mc/horse.lua +++ b/mods/ENTITIES/mobs_mc/horse.lua @@ -281,10 +281,6 @@ local horse = { return end - if mobs:protect(self, clicker) then - return - end - -- Make sure tamed horse is mature and being clicked by owner only if self.tamed and not self.child and self.owner == clicker:get_player_name() then @@ -355,7 +351,7 @@ local horse = { self.object:set_properties({stepheight = 1.1}) mobs.attach(self, clicker) - + end end end, diff --git a/mods/ENTITIES/mobs_mc/llama.lua b/mods/ENTITIES/mobs_mc/llama.lua index 5951f9dffb..e0c353ad8b 100644 --- a/mods/ENTITIES/mobs_mc/llama.lua +++ b/mods/ENTITIES/mobs_mc/llama.lua @@ -133,7 +133,6 @@ mobs:register_mob("mobs_mc:llama", { -- Feed with anything else if mobs:feed_tame(self, clicker, 1, false, true) then return end end - if mobs:protect(self, clicker) then return end -- Make sure tamed llama is mature and being clicked by owner only if self.tamed and not self.child and self.owner == clicker:get_player_name() then @@ -182,7 +181,7 @@ mobs:register_mob("mobs_mc:llama", { self.object:set_properties({stepheight = 1.1}) mobs.attach(self, clicker) end - + end end, diff --git a/mods/ENTITIES/mobs_mc/ocelot.lua b/mods/ENTITIES/mobs_mc/ocelot.lua index 139b687853..bb62a54fab 100644 --- a/mods/ENTITIES/mobs_mc/ocelot.lua +++ b/mods/ENTITIES/mobs_mc/ocelot.lua @@ -121,7 +121,6 @@ cat.sounds = { } cat.on_rightclick = function(self, clicker) if mobs:feed_tame(self, clicker, 1, true, false) then return end - if mobs:protect(self, clicker) then return end if self.child then return end diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index 06a2dc18ba..ef82884aa6 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -85,7 +85,6 @@ mobs:register_mob("mobs_mc:parrot", { -- Feed to tame, but not breed if mobs:feed_tame(self, clicker, 1, false, true) then return end - if mobs:protect(self, clicker) then return end end, }) diff --git a/mods/ENTITIES/mobs_mc/pig.lua b/mods/ENTITIES/mobs_mc/pig.lua index da7e686ada..2751a8bebd 100644 --- a/mods/ENTITIES/mobs_mc/pig.lua +++ b/mods/ENTITIES/mobs_mc/pig.lua @@ -95,7 +95,6 @@ mobs:register_mob("mobs_mc:pig", { if wielditem:get_name() ~= mobs_mc.items.carrot_on_a_stick then if mobs:feed_tame(self, clicker, 1, true, true) then return end end - if mobs:protect(self, clicker) then return end if self.child then return diff --git a/mods/ENTITIES/mobs_mc/rabbit.lua b/mods/ENTITIES/mobs_mc/rabbit.lua index 0f67bb7d7c..a7d5d02d95 100644 --- a/mods/ENTITIES/mobs_mc/rabbit.lua +++ b/mods/ENTITIES/mobs_mc/rabbit.lua @@ -61,7 +61,6 @@ local rabbit = { on_rightclick = function(self, clicker) -- Feed, tame protect or capture if mobs:feed_tame(self, clicker, 1, true, true) then return end - if mobs:protect(self, clicker) then return end end, do_custom = function(self) -- Easter egg: Change texture if rabbit is named “Toast” diff --git a/mods/ENTITIES/mobs_mc/sheep.lua b/mods/ENTITIES/mobs_mc/sheep.lua index 8ba8aecd8f..e6368a3f8a 100644 --- a/mods/ENTITIES/mobs_mc/sheep.lua +++ b/mods/ENTITIES/mobs_mc/sheep.lua @@ -195,7 +195,6 @@ mobs:register_mob("mobs_mc:sheep", { local item = clicker:get_wielded_item() if mobs:feed_tame(self, clicker, 1, true, true) then return end - if mobs:protect(self, clicker) then return end if item:get_name() == mobs_mc.items.shears and not self.gotten and not self.child then self.gotten = true diff --git a/mods/ENTITIES/mobs_mc/wolf.lua b/mods/ENTITIES/mobs_mc/wolf.lua index 319a4f9594..00a41b6855 100644 --- a/mods/ENTITIES/mobs_mc/wolf.lua +++ b/mods/ENTITIES/mobs_mc/wolf.lua @@ -147,9 +147,7 @@ dog.specific_attack = nil dog.on_rightclick = function(self, clicker) local item = clicker:get_wielded_item() - if mobs:protect(self, clicker) then - return - elseif is_food(item:get_name()) then + if is_food(item:get_name()) then -- Feed to increase health local hp = self.health local hp_add = 0 From 3d776138e97b904c9b299119ae9b9a8a2811ae7a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 14:55:22 -0400 Subject: [PATCH 082/117] Start implementing creeper ai --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 ++ mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 4 ++++ mods/ENTITIES/mobs_mc/creeper.lua | 3 +++ 3 files changed, 9 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 67865da6eb..64066ce21a 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -318,6 +318,8 @@ function mobs:register_mob(name, def) swim_in = def.swim_in or {mobs_mc.items.water_source, "mcl_core:water_flowing", mobs_mc.items.river_water_source}, pitch_switch = "static", jump_only = def.jump_only, + hostile = def.hostile, + neutral = def.neutral, --end j4i stuff -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index ce3e468b3c..1c40461889 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -596,6 +596,10 @@ mobs.mob_step = function(self, dtime) end + if self.hostile then + print("I'm a bad boi") + end + -- can mob be pushed, if so calculate direction -- do this last (overrides everything) if self.pushable then mobs.collision(self) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 0c884d5699..627ac50615 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -12,6 +12,9 @@ local S = minetest.get_translator("mobs_mc") mobs:register_mob("mobs_mc:creeper", { type = "monster", spawn_class = "hostile", + hostile = true, + neutral = false, + rotate = 270, hp_min = 20, hp_max = 20, xp_min = 5, From ac08c6991c0ce7f9bb8d9de5880ec64a7882c3e7 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 16:39:05 -0400 Subject: [PATCH 083/117] Add in detect_players_in_area --- .../mcl_mobs/api/mob_functions/ai.lua | 9 ++- .../api/mob_functions/environment.lua | 61 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 1c40461889..ae28c8cdbc 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -597,7 +597,14 @@ mobs.mob_step = function(self, dtime) if self.hostile then - print("I'm a bad boi") + --true for line_of_sight is debug + --10 for radius is debug + --1 for eye height adjust is debug + local attacking = mobs.detect_players_in_area(self,true,10,1) + + if attacking then + print(attacking:get_player_name()) + end end -- can mob be pushed, if so calculate direction -- do this last (overrides everything) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua index 082e88543f..7935dc7cc1 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -1,3 +1,7 @@ +local minetest_line_of_sight = minetest.line_of_sight + +local vector_new = vector.new + -- default function when mobs are blown up with TNT local do_tnt = function(obj, damage) @@ -9,4 +13,61 @@ local do_tnt = function(obj, damage) return false, true, {} end +--a fast function to be able to detect only players without using objects_in_radius +mobs.detect_players_in_area = function(self, line_of_sight, radius, object_height_adder) + + line_of_sight = line_of_sight or true --fallback line_of_sight + radius = radius or 10 -- fallback radius + object_height_adder = object_height_adder or 0 --fallback entity (y height) addition for line of sight + local pos1 = self.object:get_pos() + local players_in_area = {} + local winner_player = nil + local players_detected = 0 + + --get players in radius + for _,player in pairs(minetest.get_connected_players()) do + if player and player:get_hp() > 0 then + + local pos2 = player:get_pos() + + local distance = vector.distance(pos1,pos2) + + if distance <= radius then + if line_of_sight then + --must add eye height or stuff breaks randomly because of + --seethrough nodes being a blocker (like grass) + if minetest_line_of_sight( + vector_new(pos1.x, pos1.y + object_height_adder, pos1.z), + vector_new(pos2.x, pos2.y + player:get_properties().eye_height, pos2.z) + ) then + players_detected = players_detected + 1 + players_in_area[player] = distance + end + else + players_detected = players_detected + 1 + players_in_area[player] = distance + end + end + end + end + + + --return if there's no one near by + if players_detected <= 0 then --handle negative numbers for some crazy error that could possibly happen + return nil + end + + --do a default radius max + local shortest_disance = radius + 1 + + --sort through players and find the closest player + for player,distance in pairs(players_in_area) do + if distance < shortest_disance then + shortest_disance = distance + winner_player = player + end + end + + return(winner_player) +end From 348df0fcecc2709fe088493d5665112827f08129 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 16:46:10 -0400 Subject: [PATCH 084/117] Rename detect_players_in_area to detect_closest_player_within_radius --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 2 +- mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index ae28c8cdbc..1ad9cc6592 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -600,7 +600,7 @@ mobs.mob_step = function(self, dtime) --true for line_of_sight is debug --10 for radius is debug --1 for eye height adjust is debug - local attacking = mobs.detect_players_in_area(self,true,10,1) + local attacking = mobs.detect_closest_player_within_radius(self,true,10,1) if attacking then print(attacking:get_player_name()) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua index 7935dc7cc1..b5d575ab01 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -14,7 +14,7 @@ local do_tnt = function(obj, damage) end --a fast function to be able to detect only players without using objects_in_radius -mobs.detect_players_in_area = function(self, line_of_sight, radius, object_height_adder) +mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius, object_height_adder) line_of_sight = line_of_sight or true --fallback line_of_sight radius = radius or 10 -- fallback radius From 491ef6c8f818e43ef0545963eb27b5476c95ea28 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 16:48:20 -0400 Subject: [PATCH 085/117] Add in auto mob removal if something goes horribly wrong --- mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 1ad9cc6592..223399b298 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -574,6 +574,7 @@ mobs.mob_step = function(self, dtime) --do not continue if non-existent if not self or not self.object or not self.object:get_luaentity() then + self.object:remove() return false end From 008d670ed9006d918b1ed1698a5b644de27191b1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 17:10:51 -0400 Subject: [PATCH 086/117] Remove wandering from ai --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 - .../mcl_mobs/api/mob_functions/ai.lua | 24 +++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 64066ce21a..81be0878f5 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -311,7 +311,6 @@ function mobs:register_mob(name, def) backface_culling = true, walk_timer = 0, stand_timer = 0, - wandering = true, current_animation = "", gravity = GRAVITY, swim = def.swim, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 223399b298..5500d1b962 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -92,8 +92,17 @@ end local land_state_list_wandering = {"stand", "walk"} local land_state_switch = function(self, dtime) + + + if self.hostile and attack then + self.state = + return + end + + --do math after sure not attacking self.state_timer = self.state_timer - dtime - if self.wandering and self.state_timer <= 0 then + + if self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() self.state = land_state_list_wandering[math.random(1,#land_state_list_wandering)] end @@ -203,7 +212,7 @@ local swim_state_list_wandering = {"stand", "swim"} local swim_state_switch = function(self, dtime) self.state_timer = self.state_timer - dtime - if self.wandering and self.state_timer <= 0 then + if self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() self.state = swim_state_list_wandering[math.random(1,#swim_state_list_wandering)] end @@ -335,7 +344,7 @@ local fly_state_list_wandering = {"stand", "fly"} local fly_state_switch = function(self, dtime) self.state_timer = self.state_timer - dtime - if self.wandering and self.state_timer <= 0 then + if self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() self.state = fly_state_list_wandering[math.random(1,#fly_state_list_wandering)] end @@ -482,7 +491,7 @@ local jump_state_list_wandering = {"stand", "jump"} local jump_state_switch = function(self, dtime) self.state_timer = self.state_timer - dtime - if self.wandering and self.state_timer <= 0 then + if self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() self.state = jump_state_list_wandering[math.random(1,#jump_state_list_wandering)] end @@ -603,8 +612,13 @@ mobs.mob_step = function(self, dtime) --1 for eye height adjust is debug local attacking = mobs.detect_closest_player_within_radius(self,true,10,1) + --go get the closest player ROAR >:O if attacking then - print(attacking:get_player_name()) + self.attack = attacking + + --no player in area + else + self.attack = nil end end From cdb840609dc2586b31a1e44c8c1004379ef37979 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 20:19:55 -0400 Subject: [PATCH 087/117] Add in creeper basic prototype --- mods/ENTITIES/mcl_mobs/api/api.lua | 3 + .../mcl_mobs/api/mob_functions/ai.lua | 56 +++++++++++------ .../mcl_mobs/api/mob_functions/animation.lua | 50 +++++++++++++++- .../attack_type_instructions.lua | 60 +++++++++++++++++++ mods/ENTITIES/mobs_mc/creeper.lua | 4 +- 5 files changed, 150 insertions(+), 23 deletions(-) create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 81be0878f5..5734ee1c72 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -156,6 +156,7 @@ dofile(api_path .. "environment.lua") dofile(api_path .. "interaction.lua") dofile(api_path .. "movement.lua") dofile(api_path .. "set_up.lua") +dofile(api_path .. "attack_type_instructions.lua") mobs.spawning_mobs = {} @@ -319,6 +320,8 @@ function mobs:register_mob(name, def) jump_only = def.jump_only, hostile = def.hostile, neutral = def.neutral, + attacking = nil, + visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1}, --end j4i stuff -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 5500d1b962..24942e3ec7 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -92,10 +92,9 @@ end local land_state_list_wandering = {"stand", "walk"} local land_state_switch = function(self, dtime) - - if self.hostile and attack then - self.state = + if self.hostile and self.attacking then + self.state = "attack" return end @@ -132,6 +131,11 @@ local land_state_execution = function(self,dtime) --set the velocity of the mob mobs.set_velocity(self,0) + --animation fixes for explosive mobs + if self.attack_type == "explode" then + mobs.reverse_explosion_animation(self,dtime) + end + elseif self.state == "walk" then self.walk_timer = self.walk_timer - dtime @@ -178,13 +182,20 @@ local land_state_execution = function(self,dtime) mobs.set_velocity(self,self.walk_velocity) end + --animation fixes for explosive mobs + if self.attack_type == "explode" then + mobs.reverse_explosion_animation(self,dtime) + end + elseif self.state == "run" then print("run") elseif self.state == "attack" then - print("attack") + if self.attack_type == "explode" then + mobs.explode_attack_walk(self, dtime) + end end @@ -587,6 +598,29 @@ mobs.mob_step = function(self, dtime) return false end + + if self.hostile then + --true for line_of_sight is debug + --10 for radius is debug + --1 for eye height adjust is debug + local attacking = mobs.detect_closest_player_within_radius(self,true,10,1) + + --go get the closest player ROAR >:O + if attacking then + self.attacking = attacking + --no player in area + else + + --reset states when coming out of hostile state + if self.attacking ~= nil then + self.state_timer = -1 + end + + self.attacking = nil + end + end + + --jump only (like slimes) if self.jump_only then jump_state_switch(self, dtime) @@ -606,21 +640,7 @@ mobs.mob_step = function(self, dtime) end - if self.hostile then - --true for line_of_sight is debug - --10 for radius is debug - --1 for eye height adjust is debug - local attacking = mobs.detect_closest_player_within_radius(self,true,10,1) - --go get the closest player ROAR >:O - if attacking then - self.attack = attacking - - --no player in area - else - self.attack = nil - end - end -- can mob be pushed, if so calculate direction -- do this last (overrides everything) if self.pushable then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua index 97d0f7894e..b7b8fa5748 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/animation.lua @@ -1,11 +1,12 @@ local math_pi = math.pi local math_floor = math.floor +local math_random = math.random local HALF_PI = math_pi/2 - -local vector_distance = vector.distance -local vector_new = vector.new +local vector_direction = vector.direction +local vector_distance = vector.distance +local vector_new = vector.new local minetest_dir_to_yaw = minetest.dir_to_yaw @@ -114,6 +115,28 @@ mobs.movement_rotation_lock = function(self) end +--this is used when a mob is chasing a player +mobs.set_yaw_while_attacking = function(self) + + if self.object:get_properties().automatic_face_movement_dir then + self.object:set_properties{automatic_face_movement_dir = false} + end + + --turn positions into pseudo 2d vectors + local pos1 = self.object:get_pos() + pos1.y = 0 + + local pos2 = self.attacking:get_pos() + pos2.y = 0 + + local new_direction = vector_direction(pos1,pos2) + local new_yaw = minetest_dir_to_yaw(new_direction) + + self.object:set_yaw(new_yaw) + self.yaw = new_yaw +end + + local calculate_pitch = function(self) local pos = self.object:get_pos() local pos2 = self.old_pos @@ -156,4 +179,25 @@ mobs.set_static_pitch = function(self) self.object:set_rotation(current_rotation) self.pitch_switchfdas = "static" +end + +--this is a helper function for mobs explosion animation +mobs.handle_explosion_animation = function(self) + + --secondary catch-all + if not self.explosion_animation then + self.explosion_animation = 0 + end + + --the timer works from 0 for sense of a 0 based counting + --but this just bumps it up so it's usable in here + local explosion_timer_adjust = self.explosion_animation + 1 + + + local visual_size_modified = table.copy(self.visual_size_origin) + + visual_size_modified.x = visual_size_modified.x * (explosion_timer_adjust ^ 3) + visual_size_modified.y = visual_size_modified.y * explosion_timer_adjust + + self.object:set_properties({visual_size = visual_size_modified}) end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua new file mode 100644 index 0000000000..53a6ced4be --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -0,0 +1,60 @@ +local vector_direction = vector.direction +local minetest_dir_to_yaw = minetest.dir_to_yaw +local vector_distance = vector.distance + + +mobs.explode_attack_walk = function(self,dtime) + + --this needs an exception + if self.attacking == nil or not self.attacking:is_player() then + self.attacking = nil + return + end + + mobs.set_yaw_while_attacking(self) + + --make mob walk up to player within 2 nodes distance then start exploding + + --THIS NEEDS TO BE RECODED TO TAKE COLLISION BOXES INTO ACCOUNT!!! + if vector_distance(self.object:get_pos(), self.attacking:get_pos()) >= self.reach then + mobs.set_velocity(self, self.run_velocity) + mobs.set_mob_animation(self,"run") + + mobs.reverse_explosion_animation(self,dtime) + else + mobs.set_velocity(self,0) + + --this is the only way I can reference this without dumping extra data on all mobs + if not self.explosion_animation then + self.explosion_animation = 0 + end + mobs.set_mob_animation(self,"stand") + + mobs.handle_explosion_animation(self) + + self.explosion_animation = self.explosion_animation + (dtime/3) + end + + + --do biggening explosion thing + if self.explosion_animation and self.explosion_animation > self.explosion_timer then + mcl_explosions.explode(self.object:get_pos(), self.explosion_strength) + self.object:remove() + end +end + + +--this is a small helper function to make working with explosion animations easier +mobs.reverse_explosion_animation = function(self,dtime) + + + --if explosion animation was greater than 0 then reverse it + if self.explosion_animation ~= nil and self.explosion_animation > 0 then + self.explosion_animation = self.explosion_animation - dtime + if self.explosion_animation < 0 then + self.explosion_animation = 0 + end + end + + mobs.handle_explosion_animation(self) +end \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 627ac50615..6c26b422fe 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -169,8 +169,8 @@ mobs:register_mob("mobs_mc:creeper_charged", { explosion_radius = 8, explosion_damage_radius = 8, explosiontimer_reset_radius = 6, - reach = 3, - explosion_timer = 1.5, + reach = 2, + explosion_timer = 0.75, allow_fuse_reset = true, stop_to_explode = true, From 9678b556e17b124f841b0019b3a31880a415bd11 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 20:33:30 -0400 Subject: [PATCH 088/117] Fix crashes when trying to collision detect a removed mob --- mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua index 91feeb1927..47c5611bfd 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -9,6 +9,11 @@ mobs.collision = function(self) local pos = self.object:get_pos() + + if not self or not self.object or not self.object:get_luaentity() then + return + end + --do collision detection from the base of the mob local collisionbox = self.object:get_properties().collisionbox From cd6f07537f64bdbe7573642982ec24ac3fb19ec1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 20:43:45 -0400 Subject: [PATCH 089/117] Make creepers even more deadly --- .../attack_type_instructions.lua | 6 +++-- mods/ENTITIES/mobs_mc/creeper.lua | 22 +++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 53a6ced4be..edcbee1487 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -32,13 +32,15 @@ mobs.explode_attack_walk = function(self,dtime) mobs.handle_explosion_animation(self) - self.explosion_animation = self.explosion_animation + (dtime/3) + self.explosion_animation = self.explosion_animation + (dtime/2) + + print(self.explosion_animation) end --do biggening explosion thing if self.explosion_animation and self.explosion_animation > self.explosion_timer then - mcl_explosions.explode(self.object:get_pos(), self.explosion_strength) + mcl_explosions.explode(self.object:get_pos(), self.explosion_strength,{ drop_chance = 1.0 }) self.object:remove() end end diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 6c26b422fe..153d51231b 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -36,7 +36,7 @@ mobs:register_mob("mobs_mc:creeper", { explode = "tnt_explode", distance = 16, }, - makes_footstep_sound = true, + makes_footstep_sound = false, walk_velocity = 1.05, run_velocity = 2.1, runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, @@ -44,12 +44,12 @@ mobs:register_mob("mobs_mc:creeper", { --hssssssssssss - explosion_strength = 3, - explosion_radius = 3.5, - explosion_damage_radius = 3.5, + explosion_strength = 12, + explosion_radius = 6, + explosion_damage_radius = 8, explosiontimer_reset_radius = 6, reach = 3, - explosion_timer = 1.5, + explosion_timer = 0.3, allow_fuse_reset = true, stop_to_explode = true, @@ -159,18 +159,18 @@ mobs:register_mob("mobs_mc:creeper_charged", { explode = "tnt_explode", distance = 16, }, - makes_footstep_sound = true, + makes_footstep_sound = false, walk_velocity = 1.05, run_velocity = 2.1, runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, attack_type = "explode", - explosion_strength = 6, - explosion_radius = 8, - explosion_damage_radius = 8, - explosiontimer_reset_radius = 6, + explosion_strength = 24, + explosion_radius = 12, + explosion_damage_radius = 18, + explosiontimer_reset_radius = 10, reach = 2, - explosion_timer = 0.75, + explosion_timer = 0.3, allow_fuse_reset = true, stop_to_explode = true, From 0b763f54b55ea47b7889816612759447bfb50422 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 21:00:36 -0400 Subject: [PATCH 090/117] Finish creeper movement ai and move jump_check into environment --- .../mcl_mobs/api/mob_functions/ai.lua | 36 +---------------- .../attack_type_instructions.lua | 9 ++++- .../api/mob_functions/environment.lua | 39 +++++++++++++++++++ mods/ENTITIES/mobs_mc/creeper.lua | 1 + 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 24942e3ec7..6278822c4b 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -53,40 +53,6 @@ local cliff_check = function(self,dtime) return free_fall end ---check if a mob needs to jump -local jump_check = function(self,dtime) - - local pos = self.object:get_pos() - pos.y = pos.y + 0.1 - local dir = minetest_yaw_to_dir(self.yaw) - - local collisionbox = self.object:get_properties().collisionbox - local radius = collisionbox[4] + 0.5 - - vector_multiply(dir, radius) - - --only jump if there's a node and a non-solid node above it - local test_dir = vector.add(pos,dir) - - local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 - - test_dir.y = test_dir.y + 1 - - local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0 - - if green_flag_1 and green_flag_2 then - --can jump over node - return(1) - elseif green_flag_1 and not green_flag_2 then - --wall in front of mob - return(2) - end - - --nothing to jump over - return(0) -end - - -- state switching logic (stand, walk, run, attacks) local land_state_list_wandering = {"stand", "walk"} @@ -157,7 +123,7 @@ local land_state_execution = function(self,dtime) mobs.movement_rotation_lock(self) --check for nodes to jump over - local node_in_front_of = jump_check(self) + local node_in_front_of = mobs.jump_check(self) if node_in_front_of == 1 then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index edcbee1487..e0e16691d4 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -34,7 +34,14 @@ mobs.explode_attack_walk = function(self,dtime) self.explosion_animation = self.explosion_animation + (dtime/2) - print(self.explosion_animation) + end + + --make explosive mobs jump + --check for nodes to jump over + --explosive mobs will just ride against walls for now + local node_in_front_of = mobs.jump_check(self) + if node_in_front_of == 1 then + mobs.jump(self) end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua index b5d575ab01..f0aa8f45cf 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -1,6 +1,11 @@ local minetest_line_of_sight = minetest.line_of_sight +local minetest_dir_to_yaw = minetest.dir_to_yaw +local minetest_yaw_to_dir = minetest.yaw_to_dir +local minetest_get_node = minetest.get_node +local minetest_get_item_group = minetest.get_item_group local vector_new = vector.new +local vector_multiply = vector.multiply -- default function when mobs are blown up with TNT local do_tnt = function(obj, damage) @@ -71,3 +76,37 @@ mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius, return(winner_player) end + + +--check if a mob needs to jump +mobs.jump_check = function(self,dtime) + + local pos = self.object:get_pos() + pos.y = pos.y + 0.1 + local dir = minetest_yaw_to_dir(self.yaw) + + local collisionbox = self.object:get_properties().collisionbox + local radius = collisionbox[4] + 0.5 + + vector_multiply(dir, radius) + + --only jump if there's a node and a non-solid node above it + local test_dir = vector.add(pos,dir) + + local green_flag_1 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") ~= 0 + + test_dir.y = test_dir.y + 1 + + local green_flag_2 = minetest_get_item_group(minetest_get_node(test_dir).name, "solid") == 0 + + if green_flag_1 and green_flag_2 then + --can jump over node + return(1) + elseif green_flag_1 and not green_flag_2 then + --wall in front of mob + return(2) + end + + --nothing to jump over + return(0) +end \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 153d51231b..915f256ed4 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -151,6 +151,7 @@ mobs:register_mob("mobs_mc:creeper_charged", { "mobs_mc_creeper_charge.png"}, }, visual_size = {x=3, y=3}, + rotate = 270, sounds = { attack = "tnt_ignite", death = "mobs_mc_creeper_death", From bf367fffd054fe180dbc6d7f46e20e286d68bb09 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 21:34:18 -0400 Subject: [PATCH 091/117] Add in sound_handling and make explosion type mobs make their attack sound before explosion animation --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + .../attack_type_instructions.lua | 9 ++++-- .../api/mob_functions/sound_handling.lua | 32 +++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 5734ee1c72..e102430988 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -157,6 +157,7 @@ dofile(api_path .. "interaction.lua") dofile(api_path .. "movement.lua") dofile(api_path .. "set_up.lua") dofile(api_path .. "attack_type_instructions.lua") +dofile(api_path .. "sound_handling.lua") mobs.spawning_mobs = {} diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index e0e16691d4..1b89288396 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -14,8 +14,6 @@ mobs.explode_attack_walk = function(self,dtime) mobs.set_yaw_while_attacking(self) --make mob walk up to player within 2 nodes distance then start exploding - - --THIS NEEDS TO BE RECODED TO TAKE COLLISION BOXES INTO ACCOUNT!!! if vector_distance(self.object:get_pos(), self.attacking:get_pos()) >= self.reach then mobs.set_velocity(self, self.run_velocity) mobs.set_mob_animation(self,"run") @@ -28,12 +26,17 @@ mobs.explode_attack_walk = function(self,dtime) if not self.explosion_animation then self.explosion_animation = 0 end + + --play ignite sound + if self.explosion_animation == 0 then + mobs.play_sound(self,"attack") + end + mobs.set_mob_animation(self,"stand") mobs.handle_explosion_animation(self) self.explosion_animation = self.explosion_animation + (dtime/2) - end --make explosive mobs jump diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua new file mode 100644 index 0000000000..e699a1f29d --- /dev/null +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/sound_handling.lua @@ -0,0 +1,32 @@ +local math_random = math.random + + +--generic call for sound handler for mobs (data access) +mobs.play_sound = function(self,sound) + local soundinfo = self.sounds + + if not soundinfo then + return + end + + local play_sound = soundinfo[sound] + + if not play_sound then + return + end + + mobs.play_sound_handler(self, play_sound) +end + + +--generic sound handler for mobs +mobs.play_sound_handler = function(self, sound) + local pitch = (100 + math_random(-15,15) + math_random()) / 100 + + minetest.sound_play(sound, { + object = self.object, + gain = 1.0, + max_hear_distance = self.sounds.distance, + pitch = pitch, + }, true) +end \ No newline at end of file From fabd4d64e6745b9ea8c4bb1a76c190c2d66576be Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 21:35:19 -0400 Subject: [PATCH 092/117] Slow down creeper type mobs explosion buildup --- .../mcl_mobs/api/mob_functions/attack_type_instructions.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 1b89288396..9d1ba1bf30 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -36,7 +36,7 @@ mobs.explode_attack_walk = function(self,dtime) mobs.handle_explosion_animation(self) - self.explosion_animation = self.explosion_animation + (dtime/2) + self.explosion_animation = self.explosion_animation + (dtime/2.5) end --make explosive mobs jump @@ -59,7 +59,6 @@ end --this is a small helper function to make working with explosion animations easier mobs.reverse_explosion_animation = function(self,dtime) - --if explosion animation was greater than 0 then reverse it if self.explosion_animation ~= nil and self.explosion_animation > 0 then self.explosion_animation = self.explosion_animation - dtime From d371d6fdc9cb85e140399eafb89f15195f72d09f Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 22:04:54 -0400 Subject: [PATCH 093/117] Adjust creeper explosion settings --- mods/ENTITIES/mobs_mc/creeper.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 915f256ed4..830a51dafc 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -44,9 +44,9 @@ mobs:register_mob("mobs_mc:creeper", { --hssssssssssss - explosion_strength = 12, - explosion_radius = 6, - explosion_damage_radius = 8, + explosion_strength = 10, + explosion_radius = 4, + explosion_damage_radius = 6, explosiontimer_reset_radius = 6, reach = 3, explosion_timer = 0.3, From 6b52b945165a8501e09ca70c18514049df194c05 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 22:30:34 -0400 Subject: [PATCH 094/117] Start setting up hostile punch attack type --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + .../mcl_mobs/api/mob_functions/ai.lua | 15 +++++++++++ .../attack_type_instructions.lua | 25 +++++++++++++++++++ mods/ENTITIES/mobs_mc/zombie.lua | 3 +++ 4 files changed, 44 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index e102430988..1819ce0603 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -323,6 +323,7 @@ function mobs:register_mob(name, def) neutral = def.neutral, attacking = nil, visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1}, + punch_timer_cooloff = def.punch_timer_cooloff or 0.5, --end j4i stuff -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 6278822c4b..1c15f3a587 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -159,8 +159,15 @@ local land_state_execution = function(self,dtime) elseif self.state == "attack" then + --execute mob attack type if self.attack_type == "explode" then + mobs.explode_attack_walk(self, dtime) + + elseif self.attack_type == "punch" then + + mobs.punch_attack_walk(self,dtime) + end end @@ -573,6 +580,14 @@ mobs.mob_step = function(self, dtime) --go get the closest player ROAR >:O if attacking then + + --set initial punch timer + if self.attacking == nil then + if self.attack_type == "punch" then + self.punch_timer = -1 + end + end + self.attacking = attacking --no player in area else diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 9d1ba1bf30..873cc5d629 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -68,4 +68,29 @@ mobs.reverse_explosion_animation = function(self,dtime) end mobs.handle_explosion_animation(self) +end + + + + +mobs.punch_attack_walk = function(self,dtime) + + --this needs an exception + if self.attacking == nil or not self.attacking:is_player() then + self.attacking = nil + return + end + + mobs.set_yaw_while_attacking(self) + + mobs.set_velocity(self, self.run_velocity) + + mobs.set_mob_animation(self, "run") + + if self.punch_timer > 0 then + self.punch_timer = self.punch_timer - dtime + end + + print(self.punch_timer) + end \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index 4d88b25772..14377de3e4 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -48,6 +48,8 @@ table.insert(drops_zombie, { local zombie = { type = "monster", spawn_class = "hostile", + hostile = true, + rotate = 270, hp_min = 20, hp_max = 20, xp_min = 5, @@ -89,6 +91,7 @@ local zombie = { sunlight_damage = 2, view_range = 16, attack_type = "punch", + punch_timer_cooloff = 0.5, harmed_by_heal = true, } From 751c4c2d995a011a3298d374c77b9c4567ed2fa1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 22:41:13 -0400 Subject: [PATCH 095/117] Integrate mob punching into collision detection --- .../api/mob_functions/attack_type_instructions.lua | 9 ++++++++- .../mcl_mobs/api/mob_functions/collision.lua | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 873cc5d629..679ef5025a 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -90,7 +90,14 @@ mobs.punch_attack_walk = function(self,dtime) if self.punch_timer > 0 then self.punch_timer = self.punch_timer - dtime end +end - print(self.punch_timer) +mobs.punch_attack = function(self) + self.attacking:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = self.damage} + }, nil) + + self.punch_timer = self.punch_timer_cooloff end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua index 47c5611bfd..19d709329f 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -29,6 +29,13 @@ mobs.collision = function(self) local collision_count = 0 + + local check_for_attack = false + + if self.hostile and self.attacking then + check_for_attack = true + end + for _,object in ipairs(minetest_get_objects_inside_radius(pos, radius*1.25)) do if object and object ~= self.object and (object:is_player() or object:get_luaentity()._cmi_is_mob == true) then--and --don't collide with rider, rider don't collide with thing @@ -85,6 +92,13 @@ mobs.collision = function(self) if object:is_player() then vel2 = vector_multiply(vel2, 2.5) + + --integrate mob punching into collision detection + if check_for_attack and self.punch_timer <= 0 then + if object == self.attacking then + mobs.punch_attack(self) + end + end end self.object:add_velocity(vel1) From 60ac3058ce1e3e05caa87c18bdf95c78a71ed750 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 22:42:51 -0400 Subject: [PATCH 096/117] Make zombies more difficult --- mods/ENTITIES/mobs_mc/zombie.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index 14377de3e4..93550a42aa 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -71,8 +71,8 @@ local zombie = { damage = "mobs_mc_zombie_hurt", distance = 16, }, - walk_velocity = .8, - run_velocity = 1.6, + walk_velocity = 1, + run_velocity = 3, damage = 3, reach = 2, fear_height = 4, From a05ebd7cc29c96b622dbc043529513b07d5cf47b Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 22:44:34 -0400 Subject: [PATCH 097/117] Add informative text art --- .../attack_type_instructions.lua | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 679ef5025a..0f4d2bcb1c 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -1,7 +1,16 @@ local vector_direction = vector.direction local minetest_dir_to_yaw = minetest.dir_to_yaw local vector_distance = vector.distance - +--[[ + _____ _ _ +| ___| | | | | +| |____ ___ __ | | ___ __| | ___ +| __\ \/ / '_ \| |/ _ \ / _` |/ _ \ +| |___> <| |_) | | (_) | (_| | __/ +\____/_/\_\ .__/|_|\___/ \__,_|\___| + | | + |_| +]]-- mobs.explode_attack_walk = function(self,dtime) @@ -73,6 +82,17 @@ end +--[[ +______ _ +| ___ \ | | +| |_/ / _ _ __ ___| |__ +| __/ | | | '_ \ / __| '_ \ +| | | |_| | | | | (__| | | | +\_| \__,_|_| |_|\___|_| |_| +]]-- + + + mobs.punch_attack_walk = function(self,dtime) --this needs an exception From 8c9356a18cb60cd28691e3782723df763b75a1fa Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 22:58:39 -0400 Subject: [PATCH 098/117] Implement eye_height and viewing range for hostile mobs, along with making punchy mobs jump over nodes --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 4 +--- .../api/mob_functions/attack_type_instructions.lua | 9 +++++++++ mods/ENTITIES/mobs_mc/creeper.lua | 2 +- mods/ENTITIES/mobs_mc/zombie.lua | 1 + 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 1819ce0603..fcec541775 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -345,6 +345,7 @@ function mobs:register_mob(name, def) fire_resistant = def.fire_resistant or false, fire_damage_resistant = def.fire_damage_resistant or false, ignited_by_sunlight = def.ignited_by_sunlight or false, + eye_height = def.eye_height or 1.5, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 1c15f3a587..8dbe49a972 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -574,9 +574,7 @@ mobs.mob_step = function(self, dtime) if self.hostile then --true for line_of_sight is debug - --10 for radius is debug - --1 for eye height adjust is debug - local attacking = mobs.detect_closest_player_within_radius(self,true,10,1) + local attacking = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height) --go get the closest player ROAR >:O if attacking then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 0f4d2bcb1c..34a87a745b 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -107,6 +107,15 @@ mobs.punch_attack_walk = function(self,dtime) mobs.set_mob_animation(self, "run") + --make punchy mobs jump + --check for nodes to jump over + --explosive mobs will just ride against walls for now + local node_in_front_of = mobs.jump_check(self) + if node_in_front_of == 1 then + mobs.jump(self) + end + + if self.punch_timer > 0 then self.punch_timer = self.punch_timer - dtime end diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 830a51dafc..8bb0897c7d 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -41,7 +41,7 @@ mobs:register_mob("mobs_mc:creeper", { run_velocity = 2.1, runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, attack_type = "explode", - + eye_height = 1.25, --hssssssssssss explosion_strength = 10, diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index 93550a42aa..915f12e7b2 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -71,6 +71,7 @@ local zombie = { damage = "mobs_mc_zombie_hurt", distance = 16, }, + eye_height = 1.65, walk_velocity = 1, run_velocity = 3, damage = 3, From 1ed3377559c4690fa19488f526bcaf97d5ff94b1 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 23:11:18 -0400 Subject: [PATCH 099/117] Add punch mobs knockback to players when hit --- .../mob_functions/attack_type_instructions.lua | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 34a87a745b..a532cd1eb2 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -1,6 +1,7 @@ local vector_direction = vector.direction local minetest_dir_to_yaw = minetest.dir_to_yaw local vector_distance = vector.distance +local vector_multiply = vector.multiply --[[ _____ _ _ | ___| | | | | @@ -129,4 +130,20 @@ mobs.punch_attack = function(self) }, nil) self.punch_timer = self.punch_timer_cooloff + + + --knockback + local pos1 = self.object:get_pos() + pos1.y = 0 + local pos2 = self.attacking:get_pos() + pos2.y = 0 + local dir = vector_direction(pos1,pos2) + + dir = vector_multiply(dir,3) + + if self.attacking:get_velocity().y <= 1 then + dir.y = 5 + end + + self.attacking:add_velocity(dir) end \ No newline at end of file From 2c87bd19f3c6a4a5a1a3b88a45cd673ecccb838b Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 23:14:53 -0400 Subject: [PATCH 100/117] Overhaul zombie villager --- mods/ENTITIES/mobs_mc/villager_zombie.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index f6eff6e0ab..7e975fe5e2 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -28,6 +28,9 @@ local professions = { mobs:register_mob("mobs_mc:villager_zombie", { type = "monster", spawn_class = "hostile", + hostile = true, + rotate = 270, + eye_height = 1.65, hp_min = 20, hp_max = 20, xp_min = 5, From 576621169b468f317cf32d6d0be391252a033d3a Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Tue, 20 Apr 2021 23:26:18 -0400 Subject: [PATCH 101/117] Make creepers and zombies even harder --- mods/ENTITIES/mobs_mc/creeper.lua | 2 +- mods/ENTITIES/mobs_mc/villager_zombie.lua | 2 +- mods/ENTITIES/mobs_mc/zombie.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 8bb0897c7d..ee5c7fcfe1 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -38,7 +38,7 @@ mobs:register_mob("mobs_mc:creeper", { }, makes_footstep_sound = false, walk_velocity = 1.05, - run_velocity = 2.1, + run_velocity = 3.25, runaway_from = { "mobs_mc:ocelot", "mobs_mc:cat" }, attack_type = "explode", eye_height = 1.25, diff --git a/mods/ENTITIES/mobs_mc/villager_zombie.lua b/mods/ENTITIES/mobs_mc/villager_zombie.lua index 7e975fe5e2..23365e5fe6 100644 --- a/mods/ENTITIES/mobs_mc/villager_zombie.lua +++ b/mods/ENTITIES/mobs_mc/villager_zombie.lua @@ -53,7 +53,7 @@ mobs:register_mob("mobs_mc:villager_zombie", { damage = 3, reach = 2, walk_velocity = 1.2, - run_velocity = 2.4, + run_velocity = 3.5, attack_type = "punch", group_attack = true, drops = { diff --git a/mods/ENTITIES/mobs_mc/zombie.lua b/mods/ENTITIES/mobs_mc/zombie.lua index 915f12e7b2..55e9f0662b 100644 --- a/mods/ENTITIES/mobs_mc/zombie.lua +++ b/mods/ENTITIES/mobs_mc/zombie.lua @@ -73,7 +73,7 @@ local zombie = { }, eye_height = 1.65, walk_velocity = 1, - run_velocity = 3, + run_velocity = 3.5, damage = 3, reach = 2, fear_height = 4, From 486959515ca13ba0d5756ba5d930ff43e9d135b5 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 10:20:31 -0400 Subject: [PATCH 102/117] Make creepers even more dangerous --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + .../api/mob_functions/attack_type_instructions.lua | 7 ++++++- mods/ENTITIES/mobs_mc/creeper.lua | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index fcec541775..756366bbe7 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -346,6 +346,7 @@ function mobs:register_mob(name, def) fire_damage_resistant = def.fire_damage_resistant or false, ignited_by_sunlight = def.ignited_by_sunlight or false, eye_height = def.eye_height or 1.5, + defuse_reach = def.defuse_reach or 4, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index a532cd1eb2..842b79192b 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -23,8 +23,13 @@ mobs.explode_attack_walk = function(self,dtime) mobs.set_yaw_while_attacking(self) + local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos()) + --make mob walk up to player within 2 nodes distance then start exploding - if vector_distance(self.object:get_pos(), self.attacking:get_pos()) >= self.reach then + if distance_from_attacking >= self.reach and + --don't allow explosion to cancel unless out of the reach boundary + not (self.explosion_animation ~= nil and self.explosion_animation > 0 and distance_from_attacking <= self.defuse_reach) then + mobs.set_velocity(self, self.run_velocity) mobs.set_mob_animation(self,"run") diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index ee5c7fcfe1..fdc980a491 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -48,7 +48,8 @@ mobs:register_mob("mobs_mc:creeper", { explosion_radius = 4, explosion_damage_radius = 6, explosiontimer_reset_radius = 6, - reach = 3, + reach = 1.5, + defuse_reach = 4, explosion_timer = 0.3, allow_fuse_reset = true, stop_to_explode = true, From cc2a0ae52cefc388d18c9d106ef70fc0718f5e40 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 10:21:11 -0400 Subject: [PATCH 103/117] Complete charged creeper --- mods/ENTITIES/mobs_mc/creeper.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index fdc980a491..559f2e703d 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -171,7 +171,8 @@ mobs:register_mob("mobs_mc:creeper_charged", { explosion_radius = 12, explosion_damage_radius = 18, explosiontimer_reset_radius = 10, - reach = 2, + reach = 1.5, + defuse_reach = 4, explosion_timer = 0.3, allow_fuse_reset = true, stop_to_explode = true, From f1dc2864425bab2eed2f5bec7b7ccd0307145b1f Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 10:23:51 -0400 Subject: [PATCH 104/117] Dump mob_punch from backup_code_api.lua back into interaction.lua --- .../api/mob_functions/backup_code_api.lua | 274 ----------------- .../api/mob_functions/interaction.lua | 277 +++++++++++++++++- 2 files changed, 276 insertions(+), 275 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua index 2c1ba19832..0364e70c0e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua @@ -2300,280 +2300,6 @@ local day_docile = function(self) end --- deal damage and effects when mob punched -local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) - - -- custom punch function - if self.do_punch then - - -- when false skip going any further - if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then - return - end - end - - -- error checking when mod profiling is enabled - if not tool_capabilities then - minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") - return - end - - local is_player = hitter:is_player() - - if is_player then - -- is mob protected? - if self.protected and minetest_is_protected(self.object:get_pos(), hitter:get_player_name()) then - return - end - - -- set/update 'drop xp' timestamp if hitted by player - self.xp_timestamp = minetest_get_us_time() - end - - - -- punch interval - local weapon = hitter:get_wielded_item() - local punch_interval = 1.4 - - -- exhaust attacker - if mod_hunger and is_player then - mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) - end - - -- calculate mob damage - local damage = 0 - local armor = self.object:get_armor_groups() or {} - local tmp - - -- quick error check incase it ends up 0 (serialize.h check test) - if tflp == 0 then - tflp = 0.2 - end - - if use_cmi then - damage = cmi.calculate_damage(self.object, hitter, tflp, tool_capabilities, dir) - else - - for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do - - tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) - - if tmp < 0 then - tmp = 0.0 - elseif tmp > 1 then - tmp = 1.0 - end - - damage = damage + (tool_capabilities.damage_groups[group] or 0) - * tmp * ((armor[group] or 0) / 100.0) - end - end - - if weapon then - local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") - if fire_aspect_level > 0 then - mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) - end - end - - -- check for tool immunity or special damage - for n = 1, #self.immune_to do - - if self.immune_to[n][1] == weapon:get_name() then - - damage = self.immune_to[n][2] or 0 - break - end - end - - -- healing - if damage <= -1 then - self.health = self.health - math_floor(damage) - return - end - - if use_cmi then - - local cancel = cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) - - if cancel then return end - end - - if tool_capabilities then - punch_interval = tool_capabilities.full_punch_interval or 1.4 - end - - -- add weapon wear manually - -- Required because we have custom health handling ("health" property) - if minetest_is_creative_enabled("") ~= true - and tool_capabilities then - if tool_capabilities.punch_attack_uses then - -- Without this delay, the wear does not work. Quite hacky ... - minetest_after(0, function(name) - local player = minetest.get_player_by_name(name) - if not player then return end - local weapon = hitter:get_wielded_item(player) - local def = weapon:get_definition() - if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then - local wear = math_floor(65535/tool_capabilities.punch_attack_uses) - weapon:add_wear(wear) - hitter:set_wielded_item(weapon) - end - end, hitter:get_player_name()) - end - end - - local die = false - - -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. - if damage >= 0.1 then - - -- weapon sounds - if weapon:get_definition().sounds ~= nil then - - local s = math_random(0, #weapon:get_definition().sounds) - - minetest_sound_play(weapon:get_definition().sounds[s], { - object = self.object, --hitter, - max_hear_distance = 8 - }, true) - else - minetest_sound_play("default_punch", { - object = self.object, - max_hear_distance = 5 - }, true) - end - - damage_effect(self, damage) - - -- do damage - self.health = self.health - damage - - -- skip future functions if dead, except alerting others - if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then - die = true - end - - -- knock back effect (only on full punch) - if not die - and self.knock_back - and tflp >= punch_interval then - - local v = self.object:get_velocity() - local r = 1.4 - math_min(punch_interval, 1.4) - local kb = r * 2.0 - local up = 2 - - -- if already in air then dont go up anymore when hit - if v.y ~= 0 - or self.fly then - up = 0 - end - - -- direction error check - dir = dir or {x = 0, y = 0, z = 0} - - -- check if tool already has specific knockback value - if tool_capabilities.damage_groups["knockback"] then - kb = tool_capabilities.damage_groups["knockback"] - else - kb = kb * 1.5 - end - - - local luaentity - if hitter then - luaentity = hitter:get_luaentity() - end - if hitter and is_player then - local wielditem = hitter:get_wielded_item() - kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") - elseif luaentity and luaentity._knockback then - kb = kb + luaentity._knockback - end - - self.object:set_velocity({ - x = dir.x * kb, - y = dir.y * kb + up * 2, - z = dir.z * kb - }) - - self.pause_timer = 0.25 - end - end -- END if damage - - -- if skittish then run away - if not die and self.runaway == true and self.state ~= "flop" then - - local lp = hitter:get_pos() - local s = self.object:get_pos() - local vec = { - x = lp.x - s.x, - y = lp.y - s.y, - z = lp.z - s.z - } - - local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate - - if lp.x > s.x then - yaw = yaw + math_pi - end - - yaw = set_yaw(self, yaw, 6) - self.state = "runaway" - self.runaway_timer = 0 - self.following = nil - end - - local name = hitter:get_player_name() or "" - - -- attack puncher and call other mobs for help - if self.passive == false - and self.state ~= "flop" - and (self.child == false or self.type == "monster") - and hitter:get_player_name() ~= self.owner - and not mobs.invis[ name ] then - - if not die then - -- attack whoever punched mob - self.state = "" - do_attack(self, hitter) - end - - -- alert others to the attack - local objs = minetest_get_objects_inside_radius(hitter:get_pos(), self.view_range) - local obj = nil - - for n = 1, #objs do - - obj = objs[n]:get_luaentity() - - if obj then - - -- only alert members of same mob or friends - if obj.group_attack - and obj.state ~= "attack" - and obj.owner ~= name then - if obj.name == self.name then - do_attack(obj, hitter) - elseif type(obj.group_attack) == "table" then - for i=1, #obj.group_attack do - if obj.name == obj.group_attack[i] then - do_attack(obj, hitter) - break - end - end - end - end - - -- have owned mobs attack player threat - if obj.owner == name and obj.owner_loyal then - do_attack(obj, self.object) - end - end - end - end -end local mob_detach_child = function(self, child) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua index 490ae85182..b36051a382 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -37,4 +37,279 @@ mobs.create_mob_on_rightclick = function(on_rightclick) on_rightclick(self, clicker) end end -end \ No newline at end of file +end + +-- deal damage and effects when mob punched +local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) + + -- custom punch function + if self.do_punch then + + -- when false skip going any further + if self.do_punch(self, hitter, tflp, tool_capabilities, dir) == false then + return + end + end + + -- error checking when mod profiling is enabled + if not tool_capabilities then + minetest.log("warning", "[mobs] Mod profiling enabled, damage not enabled") + return + end + + local is_player = hitter:is_player() + + if is_player then + -- is mob protected? + if self.protected and minetest_is_protected(self.object:get_pos(), hitter:get_player_name()) then + return + end + + -- set/update 'drop xp' timestamp if hitted by player + self.xp_timestamp = minetest_get_us_time() + end + + + -- punch interval + local weapon = hitter:get_wielded_item() + local punch_interval = 1.4 + + -- exhaust attacker + if mod_hunger and is_player then + mcl_hunger.exhaust(hitter:get_player_name(), mcl_hunger.EXHAUST_ATTACK) + end + + -- calculate mob damage + local damage = 0 + local armor = self.object:get_armor_groups() or {} + local tmp + + -- quick error check incase it ends up 0 (serialize.h check test) + if tflp == 0 then + tflp = 0.2 + end + + if use_cmi then + damage = cmi.calculate_damage(self.object, hitter, tflp, tool_capabilities, dir) + else + + for group,_ in pairs( (tool_capabilities.damage_groups or {}) ) do + + tmp = tflp / (tool_capabilities.full_punch_interval or 1.4) + + if tmp < 0 then + tmp = 0.0 + elseif tmp > 1 then + tmp = 1.0 + end + + damage = damage + (tool_capabilities.damage_groups[group] or 0) + * tmp * ((armor[group] or 0) / 100.0) + end + end + + if weapon then + local fire_aspect_level = mcl_enchanting.get_enchantment(weapon, "fire_aspect") + if fire_aspect_level > 0 then + mcl_burning.set_on_fire(self.object, fire_aspect_level * 4) + end + end + + -- check for tool immunity or special damage + for n = 1, #self.immune_to do + + if self.immune_to[n][1] == weapon:get_name() then + + damage = self.immune_to[n][2] or 0 + break + end + end + + -- healing + if damage <= -1 then + self.health = self.health - math_floor(damage) + return + end + + if use_cmi then + + local cancel = cmi.notify_punch(self.object, hitter, tflp, tool_capabilities, dir, damage) + + if cancel then return end + end + + if tool_capabilities then + punch_interval = tool_capabilities.full_punch_interval or 1.4 + end + + -- add weapon wear manually + -- Required because we have custom health handling ("health" property) + if minetest_is_creative_enabled("") ~= true + and tool_capabilities then + if tool_capabilities.punch_attack_uses then + -- Without this delay, the wear does not work. Quite hacky ... + minetest_after(0, function(name) + local player = minetest.get_player_by_name(name) + if not player then return end + local weapon = hitter:get_wielded_item(player) + local def = weapon:get_definition() + if def.tool_capabilities and def.tool_capabilities.punch_attack_uses then + local wear = math_floor(65535/tool_capabilities.punch_attack_uses) + weapon:add_wear(wear) + hitter:set_wielded_item(weapon) + end + end, hitter:get_player_name()) + end + end + + local die = false + + -- only play hit sound and show blood effects if damage is 1 or over; lower to 0.1 to ensure armor works appropriately. + if damage >= 0.1 then + + -- weapon sounds + if weapon:get_definition().sounds ~= nil then + + local s = math_random(0, #weapon:get_definition().sounds) + + minetest_sound_play(weapon:get_definition().sounds[s], { + object = self.object, --hitter, + max_hear_distance = 8 + }, true) + else + minetest_sound_play("default_punch", { + object = self.object, + max_hear_distance = 5 + }, true) + end + + damage_effect(self, damage) + + -- do damage + self.health = self.health - damage + + -- skip future functions if dead, except alerting others + if check_for_death(self, "hit", {type = "punch", puncher = hitter}) then + die = true + end + + -- knock back effect (only on full punch) + if not die + and self.knock_back + and tflp >= punch_interval then + + local v = self.object:get_velocity() + local r = 1.4 - math_min(punch_interval, 1.4) + local kb = r * 2.0 + local up = 2 + + -- if already in air then dont go up anymore when hit + if v.y ~= 0 + or self.fly then + up = 0 + end + + -- direction error check + dir = dir or {x = 0, y = 0, z = 0} + + -- check if tool already has specific knockback value + if tool_capabilities.damage_groups["knockback"] then + kb = tool_capabilities.damage_groups["knockback"] + else + kb = kb * 1.5 + end + + + local luaentity + if hitter then + luaentity = hitter:get_luaentity() + end + if hitter and is_player then + local wielditem = hitter:get_wielded_item() + kb = kb + 3 * mcl_enchanting.get_enchantment(wielditem, "knockback") + elseif luaentity and luaentity._knockback then + kb = kb + luaentity._knockback + end + + self.object:set_velocity({ + x = dir.x * kb, + y = dir.y * kb + up * 2, + z = dir.z * kb + }) + + self.pause_timer = 0.25 + end + end -- END if damage + + -- if skittish then run away + if not die and self.runaway == true and self.state ~= "flop" then + + local lp = hitter:get_pos() + local s = self.object:get_pos() + local vec = { + x = lp.x - s.x, + y = lp.y - s.y, + z = lp.z - s.z + } + + local yaw = (atan(vec.z / vec.x) + 3 * math_pi / 2) - self.rotate + + if lp.x > s.x then + yaw = yaw + math_pi + end + + yaw = set_yaw(self, yaw, 6) + self.state = "runaway" + self.runaway_timer = 0 + self.following = nil + end + + local name = hitter:get_player_name() or "" + + -- attack puncher and call other mobs for help + if self.passive == false + and self.state ~= "flop" + and (self.child == false or self.type == "monster") + and hitter:get_player_name() ~= self.owner + and not mobs.invis[ name ] then + + if not die then + -- attack whoever punched mob + self.state = "" + do_attack(self, hitter) + end + + -- alert others to the attack + local objs = minetest_get_objects_inside_radius(hitter:get_pos(), self.view_range) + local obj = nil + + for n = 1, #objs do + + obj = objs[n]:get_luaentity() + + if obj then + + -- only alert members of same mob or friends + if obj.group_attack + and obj.state ~= "attack" + and obj.owner ~= name then + if obj.name == self.name then + do_attack(obj, hitter) + elseif type(obj.group_attack) == "table" then + for i=1, #obj.group_attack do + if obj.name == obj.group_attack[i] then + do_attack(obj, hitter) + break + end + end + end + end + + -- have owned mobs attack player threat + if obj.owner == name and obj.owner_loyal then + do_attack(obj, self.object) + end + end + end + end +end From b0b1ec9436776fdc89edaf3046499a9e2cfaed0f Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 10:53:20 -0400 Subject: [PATCH 105/117] Implement zombie pigmen and make them turn hostile when punched --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 +- .../mcl_mobs/api/mob_functions/interaction.lua | 13 ++++++++++++- mods/ENTITIES/mobs_mc/zombiepig.lua | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 756366bbe7..bafad36518 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -357,7 +357,7 @@ function mobs:register_mob(name, def) --do_punch = def.do_punch, - --on_punch = mob_punch, + on_punch = mobs.mob_punch, --on_breed = def.on_breed, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua index b36051a382..17a48e931f 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -1,3 +1,5 @@ +local math_floor = math.floor + mobs.feed_tame = function(self) return nil end @@ -40,8 +42,16 @@ mobs.create_mob_on_rightclick = function(on_rightclick) end -- deal damage and effects when mob punched -local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) +mobs.mob_punch = function(self, hitter, tflp, tool_capabilities, dir) + if self.neutral then + self.hostile = true + --hostile_cooldown timer is initialized here + self.hostile_cooldown_timer + end + + + --[[ -- custom punch function if self.do_punch then @@ -312,4 +322,5 @@ local mob_punch = function(self, hitter, tflp, tool_capabilities, dir) end end end + ]]-- end diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index efaf1b3967..4777cd7cb9 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -14,6 +14,8 @@ local pigman = { -- type="animal", passive=false: This combination is needed for a neutral mob which becomes hostile, if attacked type = "animal", passive = false, + neutral = true, + rotate = 270, spawn_class = "passive", hp_min = 20, hp_max = 20, From 5062d56a5d89346234f6125848799f32915b31a4 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 11:00:02 -0400 Subject: [PATCH 106/117] Implement neutral mob mechanics and partial implement of zombie pigmen --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua | 14 +++++++++++++- .../mcl_mobs/api/mob_functions/interaction.lua | 2 +- mods/ENTITIES/mobs_mc/creeper.lua | 1 - mods/ENTITIES/mobs_mc/zombiepig.lua | 1 + 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index bafad36518..37676f476c 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -347,6 +347,7 @@ function mobs:register_mob(name, def) ignited_by_sunlight = def.ignited_by_sunlight or false, eye_height = def.eye_height or 1.5, defuse_reach = def.defuse_reach or 4, + hostile_cooldown = def.hostile_cooldown or 15, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 8dbe49a972..f735576ced 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -571,10 +571,11 @@ mobs.mob_step = function(self, dtime) return false end + local attacking = nil if self.hostile then --true for line_of_sight is debug - local attacking = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height) + attacking = mobs.detect_closest_player_within_radius(self,true,self.view_range,self.eye_height) --go get the closest player ROAR >:O if attacking then @@ -599,6 +600,17 @@ mobs.mob_step = function(self, dtime) end end + --count down hostile cooldown timer when no players in range + if self.neutral and self.hostile and not attacking and self.hostile_cooldown_timer then + + self.hostile_cooldown_timer = self.hostile_cooldown_timer - dtime + + if self.hostile_cooldown_timer <= 0 then + self.hostile = false + self.hostile_cooldown_timer = 0 + end + end + --jump only (like slimes) if self.jump_only then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua index 17a48e931f..ed87710b72 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -47,7 +47,7 @@ mobs.mob_punch = function(self, hitter, tflp, tool_capabilities, dir) if self.neutral then self.hostile = true --hostile_cooldown timer is initialized here - self.hostile_cooldown_timer + self.hostile_cooldown_timer = self.hostile_cooldown end diff --git a/mods/ENTITIES/mobs_mc/creeper.lua b/mods/ENTITIES/mobs_mc/creeper.lua index 559f2e703d..b94a61dea9 100644 --- a/mods/ENTITIES/mobs_mc/creeper.lua +++ b/mods/ENTITIES/mobs_mc/creeper.lua @@ -13,7 +13,6 @@ mobs:register_mob("mobs_mc:creeper", { type = "monster", spawn_class = "hostile", hostile = true, - neutral = false, rotate = 270, hp_min = 20, hp_max = 20, diff --git a/mods/ENTITIES/mobs_mc/zombiepig.lua b/mods/ENTITIES/mobs_mc/zombiepig.lua index 4777cd7cb9..af1da2962b 100644 --- a/mods/ENTITIES/mobs_mc/zombiepig.lua +++ b/mods/ENTITIES/mobs_mc/zombiepig.lua @@ -17,6 +17,7 @@ local pigman = { neutral = true, rotate = 270, spawn_class = "passive", + hostile_cooldown = 15, --seconds hp_min = 20, hp_max = 20, xp_min = 6, From 964ce9ccf7101aef387bdd5ec2213ba4ac361a51 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 11:42:01 -0400 Subject: [PATCH 107/117] Temporarily disable spawn eggs from setting owner --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 37676f476c..b5a7d5579d 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -631,11 +631,13 @@ function mobs:register_egg(mob, desc, background, addegg, no_creative) local ent = mob:get_luaentity() -- don't set owner if monster or sneak pressed + --[[ if ent.type ~= "monster" and not placer:get_player_control().sneak then ent.owner = placer:get_player_name() ent.tamed = true end + ]]-- -- set nametag local nametag = itemstack:get_meta():get_string("name") From 6bd279255c7e4b5623afa39caae8f988127f7ac3 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 11:50:22 -0400 Subject: [PATCH 108/117] Fully implement zombie pigmen --- .../api/mob_functions/environment.lua | 56 +++++++++++++++++++ .../api/mob_functions/interaction.lua | 13 +++++ 2 files changed, 69 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua index f0aa8f45cf..f4e0a3809f 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -3,10 +3,13 @@ local minetest_dir_to_yaw = minetest.dir_to_yaw local minetest_yaw_to_dir = minetest.yaw_to_dir local minetest_get_node = minetest.get_node local minetest_get_item_group = minetest.get_item_group +local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius local vector_new = vector.new local vector_multiply = vector.multiply +local table_copy = table.copy + -- default function when mobs are blown up with TNT local do_tnt = function(obj, damage) @@ -109,4 +112,57 @@ mobs.jump_check = function(self,dtime) --nothing to jump over return(0) +end + +-- a helper function to quickly turn neutral passive mobs hostile +local turn_hostile = function(self,detected_mob) + --drop in variables for attacking (stops crash) + detected_mob.punch_timer = 0 + --set to hostile + detected_mob.hostile = true + --hostile_cooldown timer is initialized here + detected_mob.hostile_cooldown_timer = detected_mob.hostile_cooldown + --set target to the same + detected_mob.attacking = self.attacking +end + +--allow hostile mobs to signal to other mobs +--to switch from neutal passive to neutral hostile +mobs.group_attack_initialization = function(self) + + --get basic data + local friends_list = table_copy(self.group_attack) + local objects_in_area = minetest_get_objects_inside_radius(self.object:get_pos(), self.view_range) + + --get the player's name + local name = self.attacking:get_player_name() + + --re-use local variable + local detected_mob + + --run through mobs in viewing distance + for _,object in pairs(objects_in_area) do + if object and object:get_luaentity() then + detected_mob = object:get_luaentity() + -- only alert members of same mob or friends + if detected_mob._cmi_is_mob and detected_mob.state ~= "attack" and detected_mob.owner ~= name then + if detected_mob.name == self.name then + turn_hostile(self,detected_mob) + elseif type(detected_mob.group_attack) == "table" then + for _,id in pairs(self.group_attack) do + if detected_mob.name == id then + turn_hostile(self,detected_mob) + break + end + end + end + end + + --THIS NEEDS TO BE RE-IMPLEMENTED AS A GLOBAL HIT IN MOB_PUNCH!! + -- have owned mobs attack player threat + --if obj.owner == name and obj.owner_loyal then + -- do_attack(obj, self.object) + --end + end + end end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua index ed87710b72..94507c4cc0 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -32,6 +32,7 @@ local on_rightclick_prefix = function(self, clicker) return false end +-- I have no idea what this does mobs.create_mob_on_rightclick = function(on_rightclick) return function(self, clicker) local stop = on_rightclick_prefix(self, clicker) @@ -41,13 +42,25 @@ mobs.create_mob_on_rightclick = function(on_rightclick) end end + -- deal damage and effects when mob punched mobs.mob_punch = function(self, hitter, tflp, tool_capabilities, dir) + --neutral passive mobs switch to neutral hostile if self.neutral then + + --drop in variables for attacking (stops crash) + self.attacking = hitter + self.punch_timer = 0 + self.hostile = true --hostile_cooldown timer is initialized here self.hostile_cooldown_timer = self.hostile_cooldown + + --initialize the group attack (check for other mobs in area, make them neutral hostile) + if self.group_attack then + mobs.group_attack_initialization(self) + end end From 74094938bb0918df12ffa778c95b966d7bd6c9f3 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 12:10:29 -0400 Subject: [PATCH 109/117] Fix crash with non-punch attack mobs in collision --- mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua index 19d709329f..be707b22bd 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -32,7 +32,7 @@ mobs.collision = function(self) local check_for_attack = false - if self.hostile and self.attacking then + if self.attack_type == "punch" and self.hostile and self.attacking then check_for_attack = true end From 99e808296b81f37a9e01d4b4beb02120526bb4e9 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 12:17:51 -0400 Subject: [PATCH 110/117] Add missing skeleton/stray run animation --- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index da3df4664b..0cf44efca4 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -15,6 +15,8 @@ local mod_bows = minetest.get_modpath("mcl_bows") ~= nil local skeleton = { type = "monster", spawn_class = "hostile", + hostile = true, + rotate = 270, hp_min = 20, hp_max = 20, xp_min = 6, @@ -73,6 +75,8 @@ local skeleton = { walk_speed = 15, walk_start = 40, walk_end = 60, + run_start = 40, + run_end = 60, run_speed = 30, shoot_start = 70, shoot_end = 90, From c9f71d66f52f2e80fea6cd01fcb2db30ae399c39 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 12:42:34 -0400 Subject: [PATCH 111/117] Implement skeletons/strays --- mods/ENTITIES/mcl_mobs/api/api.lua | 1 + .../mcl_mobs/api/mob_functions/ai.lua | 6 +- .../attack_type_instructions.lua | 55 +++++++++++++++++++ .../api/mob_functions/interaction.lua | 19 +++++++ mods/ENTITIES/mobs_mc/skeleton+stray.lua | 4 +- 5 files changed, 83 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index b5a7d5579d..d9e02f46d0 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -324,6 +324,7 @@ function mobs:register_mob(name, def) attacking = nil, visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1}, punch_timer_cooloff = def.punch_timer_cooloff or 0.5, + projectile_cooldown = projectile_cooldown or 2, --end j4i stuff -- MCL2 extensions diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index f735576ced..347471be3e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -168,6 +168,10 @@ local land_state_execution = function(self,dtime) mobs.punch_attack_walk(self,dtime) + elseif self.attack_type == "projectile" then + + mobs.projectile_attack_walk(self,dtime) + end end @@ -602,7 +606,7 @@ mobs.mob_step = function(self, dtime) --count down hostile cooldown timer when no players in range if self.neutral and self.hostile and not attacking and self.hostile_cooldown_timer then - + self.hostile_cooldown_timer = self.hostile_cooldown_timer - dtime if self.hostile_cooldown_timer <= 0 then diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 842b79192b..35fe2f892e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -2,6 +2,7 @@ local vector_direction = vector.direction local minetest_dir_to_yaw = minetest.dir_to_yaw local vector_distance = vector.distance local vector_multiply = vector.multiply + --[[ _____ _ _ | ___| | | | | @@ -151,4 +152,58 @@ mobs.punch_attack = function(self) end self.attacking:add_velocity(dir) +end + + + + +--[[ +______ _ _ _ _ +| ___ \ (_) | | (_) | +| |_/ / __ ___ _ ___ ___| |_ _| | ___ +| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \ +| | | | | (_) | | __/ (__| |_| | | __/ +\_| |_| \___/| |\___|\___|\__|_|_|\___| + _/ | + |__/ +]]-- + + +mobs.projectile_attack_walk = function(self,dtime) + + --this needs an exception + if self.attacking == nil or not self.attacking:is_player() then + self.attacking = nil + return + end + + mobs.set_yaw_while_attacking(self) + + local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos()) + + + if distance_from_attacking >= self.reach then + mobs.set_velocity(self, self.run_velocity) + mobs.set_mob_animation(self,"run") + else + mobs.set_velocity(self,0) + mobs.set_mob_animation(self,"stand") + end + + --do this to not load data into other mobs + if not self.projectile_timer then + self.projectile_timer = self.projectile_cooldown + end + + if self.projectile_timer > 0 then + self.projectile_timer = self.projectile_timer - dtime + + --shoot + if self.projectile_timer <= 0 then + --reset timer + self.projectile_timer = self.projectile_cooldown + mobs.shoot_projectile(self) + end + end + end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua index 94507c4cc0..7cbcd9a706 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/interaction.lua @@ -1,4 +1,5 @@ local math_floor = math.floor +local vector_direction = vector.direction mobs.feed_tame = function(self) return nil @@ -337,3 +338,21 @@ mobs.mob_punch = function(self, hitter, tflp, tool_capabilities, dir) end ]]-- end + +--do internal per mob projectile calculations +mobs.shoot_projectile = function(self) + + local pos1 = self.object:get_pos() + --add mob eye height + pos1.y = pos1.y + self.eye_height + + local pos2 = self.attacking:get_pos() + --add player eye height + pos2.y = pos2.y + self.attacking:get_properties().eye_height + + --get direction + local dir = vector_direction(pos1,pos2) + + --call internal shoot_arrow function + self.shoot_arrow(self,pos1,dir) +end \ No newline at end of file diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index 0cf44efca4..a14ec62d1e 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -22,6 +22,8 @@ local skeleton = { xp_min = 6, xp_max = 6, breath_max = -1, + eye_height = 1.5, + projectile_cooldown = 1.5, armor = {undead = 100, fleshy = 100}, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.98, 0.3}, pathfinding = 1, @@ -43,7 +45,7 @@ local skeleton = { walk_velocity = 1.2, run_velocity = 2.4, damage = 2, - reach = 2, + reach = 3, drops = { {name = mobs_mc.items.arrow, chance = 1, From ebd995fbd2eb089a37b659e9ae87c86562e3ed69 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 12:45:02 -0400 Subject: [PATCH 112/117] Simplify skeleton arrow damage calculation --- mods/ENTITIES/mobs_mc/skeleton+stray.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/ENTITIES/mobs_mc/skeleton+stray.lua b/mods/ENTITIES/mobs_mc/skeleton+stray.lua index a14ec62d1e..0c6cacc207 100644 --- a/mods/ENTITIES/mobs_mc/skeleton+stray.lua +++ b/mods/ENTITIES/mobs_mc/skeleton+stray.lua @@ -95,7 +95,7 @@ local skeleton = { shoot_arrow = function(self, pos, dir) if mod_bows then -- 2-4 damage per arrow - local dmg = math.max(4, math.random(2, 8)) + local dmg = math.random(2,4) mcl_bows.shoot_arrow("mcl_bows:arrow", pos, dir, self.object:get_yaw(), self.object, nil, dmg) end end, From 20886f54bb8887fb88ce0e0e0c6f28a789868740 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 12:48:23 -0400 Subject: [PATCH 113/117] Make shooty mobs jump --- .../api/mob_functions/attack_type_instructions.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 35fe2f892e..452aa3ec23 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -206,4 +206,12 @@ mobs.projectile_attack_walk = function(self,dtime) end end + --make shooty mobs jump + --check for nodes to jump over + --explosive mobs will just ride against walls for now + local node_in_front_of = mobs.jump_check(self) + if node_in_front_of == 1 then + mobs.jump(self) + end + end \ No newline at end of file From 71c34823bc87b0892d4450b877fb1c78cd6ad416 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 12:56:36 -0400 Subject: [PATCH 114/117] Make tilt flying/swimming dynamic --- mods/ENTITIES/mcl_mobs/api/api.lua | 2 ++ .../mcl_mobs/api/mob_functions/ai.lua | 25 ++++++++++++++----- .../attack_type_instructions.lua | 1 + mods/ENTITIES/mobs_mc/blaze.lua | 1 + 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index d9e02f46d0..c08b811865 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -349,6 +349,8 @@ function mobs:register_mob(name, def) eye_height = def.eye_height or 1.5, defuse_reach = def.defuse_reach or 4, hostile_cooldown = def.hostile_cooldown or 15, + tilt_fly = def.tilt_fly or true, + tilt_swim = def.tilt_swim or true, -- End of MCL2 extensions on_spawn = def.on_spawn, diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 347471be3e..4c85d9b3a5 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -271,7 +271,9 @@ local swim_state_execution = function(self,dtime) mobs.set_swim_velocity(self,0) - mobs.set_static_pitch(self) + if self.tilt_swim then + mobs.set_static_pitch(self) + end elseif self.state == "swim" then @@ -301,7 +303,10 @@ local swim_state_execution = function(self,dtime) mobs.set_swim_velocity(self,self.walk_velocity) - mobs.set_dynamic_pitch(self) + --only enable tilt swimming if enabled + if self.tilt_swim then + mobs.set_dynamic_pitch(self) + end end --flop around if not inside swim node else @@ -310,7 +315,9 @@ local swim_state_execution = function(self,dtime) mobs.flop(self) - mobs.set_static_pitch(self) + if self.tilt_swim then + mobs.set_static_pitch(self) + end end end @@ -398,7 +405,9 @@ local fly_state_execution = function(self,dtime) mobs.set_fly_velocity(self,0) - mobs.set_static_pitch(self) + if self.tilt_fly then + mobs.set_static_pitch(self) + end elseif self.state == "fly" then @@ -426,7 +435,9 @@ local fly_state_execution = function(self,dtime) quick_rotate(self,dtime) end - mobs.set_dynamic_pitch(self) + if self.tilt_fly then + mobs.set_dynamic_pitch(self) + end mobs.set_fly_velocity(self,self.walk_velocity) end @@ -437,7 +448,9 @@ local fly_state_execution = function(self,dtime) mobs.float(self) - mobs.set_static_pitch(self) + if self.tilt_fly then + mobs.set_static_pitch(self) + end end end end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 452aa3ec23..13aeea0875 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -195,6 +195,7 @@ mobs.projectile_attack_walk = function(self,dtime) self.projectile_timer = self.projectile_cooldown end + --run projectile timer if self.projectile_timer > 0 then self.projectile_timer = self.projectile_timer - dtime diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index d7e0a5c48f..6bc67300f7 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -17,6 +17,7 @@ mobs:register_mob("mobs_mc:blaze", { hp_max = 20, xp_min = 10, xp_max = 10, + tilt_fly = false, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3}, rotate = -180, visual = "mesh", From 91099c3be93689c2569f838a63e75e38ca382162 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 13:01:14 -0400 Subject: [PATCH 115/117] Fix auto-true statement for tilt fly/swim --- mods/ENTITIES/mcl_mobs/api/api.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index c08b811865..7723e16a69 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -349,8 +349,8 @@ function mobs:register_mob(name, def) eye_height = def.eye_height or 1.5, defuse_reach = def.defuse_reach or 4, hostile_cooldown = def.hostile_cooldown or 15, - tilt_fly = def.tilt_fly or true, - tilt_swim = def.tilt_swim or true, + tilt_fly = def.tilt_fly, + tilt_swim = def.tilt_swim, -- End of MCL2 extensions on_spawn = def.on_spawn, From 08c90c34e83c498ee2cc883a2cad9b98a269a850 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 13:05:46 -0400 Subject: [PATCH 116/117] Make parrots and squids work with tilt fly/swim --- mods/ENTITIES/mobs_mc/parrot.lua | 1 + mods/ENTITIES/mobs_mc/squid.lua | 1 + 2 files changed, 2 insertions(+) diff --git a/mods/ENTITIES/mobs_mc/parrot.lua b/mods/ENTITIES/mobs_mc/parrot.lua index ef82884aa6..fb1bc6f9bc 100644 --- a/mods/ENTITIES/mobs_mc/parrot.lua +++ b/mods/ENTITIES/mobs_mc/parrot.lua @@ -19,6 +19,7 @@ mobs:register_mob("mobs_mc:parrot", { hp_max = 6, xp_min = 1, xp_max = 3, + tilt_fly = true, collisionbox = {-0.25, -0.01, -0.25, 0.25, 0.89, 0.25}, visual = "mesh", mesh = "mobs_mc_parrot.b3d", diff --git a/mods/ENTITIES/mobs_mc/squid.lua b/mods/ENTITIES/mobs_mc/squid.lua index 09fa8b1283..53e99f7f92 100644 --- a/mods/ENTITIES/mobs_mc/squid.lua +++ b/mods/ENTITIES/mobs_mc/squid.lua @@ -17,6 +17,7 @@ mobs:register_mob("mobs_mc:squid", { xp_max = 3, armor = 100, rotate = 270, + tilt_swim = true, -- FIXME: If the squid is near the floor, it turns black collisionbox = {-0.4, 0.0, -0.4, 0.4, 0.9, 0.4}, visual = "mesh", From 29305f548db88b0b895ec747ebfbc092c51c4762 Mon Sep 17 00:00:00 2001 From: jordan4ibanez Date: Wed, 21 Apr 2021 15:08:35 -0400 Subject: [PATCH 117/117] Overhaul arrow register, implement basic blaze, break parts of arrow register for now, remove fallback for detecting players --- mods/ENTITIES/mcl_mobs/api/api.lua | 51 +++++++---- .../mcl_mobs/api/mob_functions/ai.lua | 22 +++++ .../attack_type_instructions.lua | 85 +++++++++++++++++++ .../api/mob_functions/backup_code_api.lua | 32 +------ .../mcl_mobs/api/mob_functions/collision.lua | 28 ++++++ .../api/mob_functions/combat_interaction.lua | 1 - .../api/mob_functions/environment.lua | 40 ++++++++- .../mcl_mobs/api/mob_functions/movement.lua | 24 ++++++ mods/ENTITIES/mobs_mc/blaze.lua | 16 +++- 9 files changed, 245 insertions(+), 54 deletions(-) delete mode 100644 mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua diff --git a/mods/ENTITIES/mcl_mobs/api/api.lua b/mods/ENTITIES/mcl_mobs/api/api.lua index 7723e16a69..b6054f281b 100644 --- a/mods/ENTITIES/mcl_mobs/api/api.lua +++ b/mods/ENTITIES/mcl_mobs/api/api.lua @@ -48,6 +48,9 @@ local math_floor = math.floor -- localize vector functions local vector_new = vector.new local vector_length = vector.length +local vector_direction = vector.direction +local vector_normalize = vector.normalize +local vector_multiply = vector.multiply -- mob constants local MAX_MOB_NAME_LENGTH = 30 @@ -324,7 +327,7 @@ function mobs:register_mob(name, def) attacking = nil, visual_size_origin = def.visual_size or {x = 1, y = 1, z = 1}, punch_timer_cooloff = def.punch_timer_cooloff or 0.5, - projectile_cooldown = projectile_cooldown or 2, + projectile_cooldown = def.projectile_cooldown or 2, --end j4i stuff -- MCL2 extensions @@ -439,9 +442,13 @@ end -- END mobs:register_mob function -- register arrow for shoot attack function mobs:register_arrow(name, def) - if not name or not def then return end -- errorcheck + -- errorcheck + if not name or not def then + print("failed to register arrow entity") + return + end - minetest.register_entity(name, { + minetest.register_entity(name.."_entity", { physical = false, visual = def.visual, @@ -458,15 +465,17 @@ function mobs:register_arrow(name, def) switch = 0, owner_id = def.owner_id, rotate = def.rotate, - on_punch = function(self) - local vel = self.object:get_velocity() - --self.object:set_velocity({x=vel.x * -1, y=vel.y * -1, z=vel.z * -1}) - local pos = self.object:get_pos() + speed = def.speed or nil, + on_step = function(self) - if self.switch == 0 - or self.timer > 150 - or not within_limits(pos, 0) then + local vel = self.object:get_velocity() + + local pos = self.object:get_pos() + + if self.timer > 150 + or not mobs.within_limits(pos, 0) then mcl_burning.extinguish(self.object) + print("removing 1") self.object:remove(); return @@ -491,7 +500,7 @@ function mobs:register_arrow(name, def) if self.hit_node then - local node = node_ok(pos).name + local node = minetest_get_node(pos).name if minetest_registered_nodes[node].walkable then @@ -519,32 +528,42 @@ function mobs:register_arrow(name, def) if self.hit_player and player:is_player() then - self.hit_player(self, player) + mobs.arrow_hit(self, player) + + print("wow everything is fucked") self.object:remove(); return end + --[[ local entity = player:get_luaentity() if entity and self.hit_mob and entity._cmi_is_mob == true and tostring(player) ~= self.owner_id - and entity.name ~= self.object:get_luaentity().name then - self.hit_mob(self, player) + and entity.name ~= self.object:get_luaentity().name + and (self._shooter and entity.name ~= self._shooter:get_luaentity().name) then + + --self.hit_mob(self, player) self.object:remove(); return end + ]]-- + --[[ if entity and self.hit_object and (not entity._cmi_is_mob) and tostring(player) ~= self.owner_id - and entity.name ~= self.object:get_luaentity().name then - self.hit_object(self, player) + and entity.name ~= self.object:get_luaentity().name + and (self._shooter and entity.name ~= self._shooter:get_luaentity().name) then + + --self.hit_object(self, player) self.object:remove(); return end + ]]-- end end diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua index 4c85d9b3a5..11c61f20f4 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/ai.lua @@ -338,6 +338,12 @@ ______ _ local fly_state_list_wandering = {"stand", "fly"} local fly_state_switch = function(self, dtime) + + if self.hostile and self.attacking then + self.state = "attack" + return + end + self.state_timer = self.state_timer - dtime if self.state_timer <= 0 then self.state_timer = math.random(4,10) + math.random() @@ -440,6 +446,22 @@ local fly_state_execution = function(self,dtime) end mobs.set_fly_velocity(self,self.walk_velocity) + elseif self.state == "attack" then + + --execute mob attack type + --if self.attack_type == "explode" then + + --mobs.explode_attack_fly(self, dtime) + + --elseif self.attack_type == "punch" then + + --mobs.punch_attack_fly(self,dtime) + + if self.attack_type == "projectile" then + + mobs.projectile_attack_fly(self,dtime) + + end end else --make the mob float diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua index 13aeea0875..e60c46aab1 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/attack_type_instructions.lua @@ -3,6 +3,17 @@ local minetest_dir_to_yaw = minetest.dir_to_yaw local vector_distance = vector.distance local vector_multiply = vector.multiply +--[[ + _ _ _ _ +| | | | | | | | +| | | | __ _ _ __ __| | | | +| | | | / _` | '_ \ / _` | | | +|_| | |___| (_| | | | | (_| | |_| +(_) \_____/\__,_|_| |_|\__,_| (_) +]]-- + + + --[[ _____ _ _ | ___| | | | | @@ -215,4 +226,78 @@ mobs.projectile_attack_walk = function(self,dtime) mobs.jump(self) end +end + + + + + + + + + +--[[ + _ ______ _ _ +| | | ___| | | | +| | | |_ | |_ _ | | +| | | _| | | | | | | | +|_| | | | | |_| | |_| +(_) \_| |_|\__, | (_) + __/ | + |___/ +]]-- + + + + +--[[ +______ _ _ _ _ +| ___ \ (_) | | (_) | +| |_/ / __ ___ _ ___ ___| |_ _| | ___ +| __/ '__/ _ \| |/ _ \/ __| __| | |/ _ \ +| | | | | (_) | | __/ (__| |_| | | __/ +\_| |_| \___/| |\___|\___|\__|_|_|\___| + _/ | + |__/ +]]-- + +mobs.projectile_attack_fly = function(self, dtime) + + --this needs an exception + if self.attacking == nil or not self.attacking:is_player() then + self.attacking = nil + return + end + + local distance_from_attacking = vector_distance(self.object:get_pos(), self.attacking:get_pos()) + + if distance_from_attacking >= self.reach then + mobs.set_yaw_while_attacking(self) + mobs.set_pitch_while_attacking(self) + mobs.set_fly_velocity(self, self.run_velocity) + mobs.set_mob_animation(self,"run") + else + mobs.set_yaw_while_attacking(self) + mobs.set_pitch_while_attacking(self) + mobs.set_fly_velocity(self, 0) + mobs.set_mob_animation(self,"stand") + end + + + --do this to not load data into other mobs + if not self.projectile_timer then + self.projectile_timer = self.projectile_cooldown + end + + --run projectile timer + if self.projectile_timer > 0 then + self.projectile_timer = self.projectile_timer - dtime + + --shoot + if self.projectile_timer <= 0 then + --reset timer + self.projectile_timer = self.projectile_cooldown + mobs.shoot_projectile(self) + end + end end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua index 0364e70c0e..802201688e 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/backup_code_api.lua @@ -1565,25 +1565,7 @@ local function update_roll(self) self.object:set_properties({collisionbox = cbox}) end --- check if within physical map limits (-30911 to 30927) -local within_limits, wmin, wmax = nil, -30913, 30928 -within_limits = function(pos, radius) - if mcl_vars then - if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then - wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max - within_limits = function(pos, radius) - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax - end - end - end - return pos - and (pos.x - radius) > wmin and (pos.x + radius) < wmax - and (pos.y - radius) > wmin and (pos.y + radius) < wmax - and (pos.z - radius) > wmin and (pos.z + radius) < wmax -end + -- is mob facing a cliff or danger local is_at_cliff_or_danger = function(self) @@ -1661,19 +1643,7 @@ local is_at_water_danger = function(self) end --- get node but use fallback for nil or unknown -local node_ok = function(pos, fallback) - fallback = fallback or mobs.fallback_node - - local node = minetest_get_node_or_nil(pos) - - if node and minetest_registered_nodes[node.name] then - return node - end - - return minetest_registered_nodes[fallback] -end -- environmental damage (water, lava, fire, light etc.) diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua index be707b22bd..43b7592692 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/collision.lua @@ -3,6 +3,8 @@ local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius local math_random = math.random local vector_multiply = vector.multiply +local vector_direction = vector.direction + local integer_test = {-1,1} mobs.collision = function(self) @@ -107,4 +109,30 @@ mobs.collision = function(self) end end +end + + +--this is used for arrow collisions +mobs.arrow_hit = function(self, player) + + player:punch(self.object, 1.0, { + full_punch_interval = 1.0, + damage_groups = {fleshy = self._damage} + }, nil) + + + --knockback + local pos1 = self.object:get_pos() + pos1.y = 0 + local pos2 = player:get_pos() + pos2.y = 0 + local dir = vector_direction(pos1,pos2) + + dir = vector_multiply(dir,3) + + if player:get_velocity().y <= 1 then + dir.y = 5 + end + + player:add_velocity(dir) end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua deleted file mode 100644 index 5ba67b28c5..0000000000 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/combat_interaction.lua +++ /dev/null @@ -1 +0,0 @@ ---make mobs scan players and check distance then if direct line of sight then add to list and go after whichever one is closer \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua index f4e0a3809f..c6a392e577 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/environment.lua @@ -4,6 +4,8 @@ local minetest_yaw_to_dir = minetest.yaw_to_dir local minetest_get_node = minetest.get_node local minetest_get_item_group = minetest.get_item_group local minetest_get_objects_inside_radius = minetest.get_objects_inside_radius +local minetest_get_node_or_nil = minetest.get_node_or_nil +local minetest_registered_nodes = minetest.registered_nodes local vector_new = vector.new local vector_multiply = vector.multiply @@ -24,10 +26,6 @@ end --a fast function to be able to detect only players without using objects_in_radius mobs.detect_closest_player_within_radius = function(self, line_of_sight, radius, object_height_adder) - line_of_sight = line_of_sight or true --fallback line_of_sight - radius = radius or 10 -- fallback radius - object_height_adder = object_height_adder or 0 --fallback entity (y height) addition for line of sight - local pos1 = self.object:get_pos() local players_in_area = {} local winner_player = nil @@ -165,4 +163,38 @@ mobs.group_attack_initialization = function(self) --end end end +end + +-- check if within physical map limits (-30911 to 30927) +-- within_limits, wmin, wmax = nil, -30913, 30928 +mobs.within_limits = function(pos, radius) + if mcl_vars then + if mcl_vars.mapgen_edge_min and mcl_vars.mapgen_edge_max then + wmin, wmax = mcl_vars.mapgen_edge_min, mcl_vars.mapgen_edge_max + within_limits = function(pos, radius) + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax + end + end + end + return pos + and (pos.x - radius) > wmin and (pos.x + radius) < wmax + and (pos.y - radius) > wmin and (pos.y + radius) < wmax + and (pos.z - radius) > wmin and (pos.z + radius) < wmax +end + +-- get node but use fallback for nil or unknown +mobs.node_ok = function(pos, fallback) + + fallback = fallback or mobs.fallback_node + + local node = minetest_get_node_or_nil(pos) + + if node and minetest_registered_nodes[node.name] then + return node + end + + return minetest_registered_nodes[fallback] end \ No newline at end of file diff --git a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua index f983734ebe..811488396f 100644 --- a/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua +++ b/mods/ENTITIES/mcl_mobs/api/mob_functions/movement.lua @@ -2,14 +2,17 @@ local math_pi = math.pi local math_sin = math.sin local math_cos = math.cos local math_random = math.random +local HALF_PI = math_pi / 2 local DOUBLE_PI = math_pi * 2 -- localize vector functions local vector_new = vector.new local vector_length = vector.length local vector_multiply = vector.multiply +local vector_distance = vector.distance local minetest_yaw_to_dir = minetest.yaw_to_dir +local minetest_dir_to_yaw = minetest.dir_to_yaw local DEFAULT_JUMP_HEIGHT = 5 local DEFAULT_FLOAT_SPEED = 4 @@ -236,6 +239,27 @@ mobs.set_fly_velocity = function(self, v) end end +--a quick and simple pitch calculation between two vector positions +mobs.calculate_pitch = function(pos1, pos2) + + if pos1 == nil or pos2 == nil then + return false + end + + return(minetest_dir_to_yaw(vector_new(vector_distance(vector_new(pos1.x,0,pos1.z),vector_new(pos2.x,0,pos2.z)),0,pos1.y - pos2.y)) + HALF_PI) +end + +--make mobs fly up or down based on their y difference +mobs.set_pitch_while_attacking = function(self) + local pos1 = self.object:get_pos() + local pos2 = self.attacking:get_pos() + + local pitch = mobs.calculate_pitch(pos2,pos1) + + self.pitch = pitch +end + + --[[ ___ diff --git a/mods/ENTITIES/mobs_mc/blaze.lua b/mods/ENTITIES/mobs_mc/blaze.lua index 6bc67300f7..d88a84515c 100644 --- a/mods/ENTITIES/mobs_mc/blaze.lua +++ b/mods/ENTITIES/mobs_mc/blaze.lua @@ -18,6 +18,8 @@ mobs:register_mob("mobs_mc:blaze", { xp_min = 10, xp_max = 10, tilt_fly = false, + hostile = true, + rotate = 270, collisionbox = {-0.3, -0.01, -0.3, 0.3, 1.79, 0.3}, rotate = -180, visual = "mesh", @@ -36,7 +38,7 @@ mobs:register_mob("mobs_mc:blaze", { walk_velocity = .8, run_velocity = 1.6, damage = 6, - reach = 2, + reach = 4, -- don't want blaze getting too close pathfinding = 1, drops = { {name = mobs_mc.items.blaze_rod, @@ -76,6 +78,13 @@ mobs:register_mob("mobs_mc:blaze", { fear_height = 0, glow = 14, fire_resistant = true, + eye_height = 0.75, + shoot_arrow = function(self, pos, dir) + -- 2-4 damage per arrow + local dmg = math.random(2,4) + mcl_bows.shoot_arrow("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, nil, dmg) + end, + do_custom = function(self) if self.state == "attack" and vector.distance(self.object:get_pos(), self.attack:get_pos()) < 1.2 then mcl_burning.set_on_fire(self.attack, 5) @@ -148,6 +157,7 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { visual_size = {x = 0.3, y = 0.3}, textures = {"mcl_fire_fire_charge.png"}, velocity = 15, + speed = 5, -- Direct hit, no fire... just plenty of pain hit_player = function(self, player) @@ -180,7 +190,9 @@ mobs:register_arrow("mobs_mc:blaze_fireball", { -- Node hit, make fire hit_node = function(self, pos, node) - if node.name == "air" then + if node.name ~= "air" then + local pos_above = table.copy(pos) + pos_above.y = pos_above.y + 1 minetest.set_node(pos_above, {name=mobs_mc.items.fire}) else local v = self.object:get_velocity()