123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- local S = minetest.get_translator("mob_botete")
- local function place_goo(pos, life)
- if life == nil then
- life = 1
- elseif life <= 0 then
- return false
- end
- local node = minetest.get_node_or_nil(pos)
- if not node or node.name ~= "air" and not minetest.registered_nodes[node.name].buildable_to then
- return false
- end
- if node.name == "mob_botete:goo" then
- minetest.dig_node(pos)
- minetest.place_node(pos, {name="mob_botete:goo_block"})
- minetest.get_meta(pos):set_int("life", life)
- return true
- else
- local dirs = {
- {x = 0, y =-1, z = 0},
- {x =-1, y = 0, z = 0},
- {x = 0, y = 0, z = 1},
- {x = 0, y = 0, z =-1},
- {x = 1, y = 0, z = 0},
- {x = 0, y = 1, z = 0},
- }
- local dir = nil
- for _,d in ipairs(dirs) do
- local wall_pos = vector.add(pos, d)
- local wall = minetest.get_node_or_nil(wall_pos)
- if wall and wall.name ~= "air" and minetest.get_item_group(wall.name, "caustic_goo") == 0 then
- dir = d
- break
- end
- end
- if dir then
- local wallmounted = minetest.dir_to_wallmounted(dir)
- if minetest.registered_nodes[node.name].buildable_to then
- minetest.place_node(pos, {name="mob_botete:goo", param2=wallmounted})
- minetest.get_meta(pos):set_int("life", life)
- return true
- end
- end
- end
- return false
- end
- local function goo_consume(pos, life)
- local node = minetest.get_node_or_nil(pos)
- if not node or node.name == "air" then
- return false
- end
- local neighbors = {
- {x = 1, y = 0, z = 0},
- {x =-1, y = 0, z = 0},
- {x = 0, y = 1, z = 0},
- {x = 0, y =-1, z = 0},
- {x = 0, y = 0, z = 1},
- {x = 0, y = 0, z =-1},
- }
- local count = 0
- for _,n in ipairs(neighbors) do
- local neighbor = minetest.get_node_or_nil(vector.add(pos, n))
- if neighbor and minetest.get_item_group(neighbor.name, "caustic_goo") > 0 then
- count = count + 1
- end
- end
- if count >= math.random(2,5) then
- minetest.dig_node(pos)
- minetest.place_node(pos, {name="mob_botete:goo_block"})
- minetest.get_meta(pos):set_int("life", life)
- end
- end
- local function spread_goo(pos)
- local node = minetest.get_node_or_nil(pos)
- if node then
- local life = minetest.get_meta(pos):get_int("life") or 0
- if life > 1 then
- minetest.get_meta(pos):set_int("life", life - 1)
- local dirs = {
- {x = 1, y = 0, z = 0},
- {x =-1, y = 0, z = 0},
- {x = 0, y = 1, z = 0},
- {x = 0, y =-1, z = 0},
- {x = 0, y = 0, z = 1},
- {x = 0, y = 0, z =-1},
- }
- local dir = nil
- if node.name == "mob_botete:goo" then
- dir = minetest.wallmounted_to_dir(node.param2)
- else
- dir = dirs[4]
- end
- goo_consume(vector.add(pos, dir), life - 1)
- for _,d in ipairs(dirs) do
- local dot_product = d.x * dir.x + d.y * dir.y + d.z * dir.z
- if dot_product == 0 then
- if math.random() < 0.25 then
- local npos = vector.add(pos, d)
- if not place_goo(vector.add(npos, dir), life - 1) then
- if not place_goo(npos, life - 1) then
- place_goo(vector.subtract(npos, dir), life - 1)
- end
- end
- end
- end
- end
- end
- if life <= 1 and math.random() < 0.2 then
- minetest.dig_node(pos)
- end
- end
- end
- defense_mob_api.register_mob("mob_botete:botete", {
- hp_max = 2,
- collisionbox = {-0.6,-0.7,-0.6, 0.6,0.4,0.6},
- mesh = "mob_botete_botete.b3d",
- textures = {"mob_botete_botete.png"},
- makes_footstep_sound = false,
- animation = {
- idle = {a=0, b=39, rate=20},
- attack = {a=80, b=99, rate=25},
- move = {a=40, b=79, rate=25},
- move_attack = {a=80, b=99, rate=25},
- },
- smart_path = false,
- mass = 1,
- movement = "air",
- move_speed = 4,
- attack_damage = 0,
- attack_range = 8,
- attack_interval = 16,
- on_step = function(self, dtime)
- defense_mob_api.default_prototype.on_step(self, dtime)
- if self.last_attack_time + self.attack_interval * 0.5 < self.timer or self.last_attack_time + 0.25 > self.timer then
- self:hunt()
- elseif not self.destination then
- self.destination = vector.add(self.object:get_pos(), {x=math.random(-10,10), y=math.random(-5,6), z=math.random(-10,10)})
- self.automatic_face_movement_dir = true
- self.object:set_properties({automatic_face_movement_dir = self.automatic_face_movement_dir})
- end
- end,
- attack = function(self, obj, dir)
- local pos = self.object:get_pos()
- local hdir = vector.normalize({x=dir.x, y=0, z=dir.z})
- pos = vector.add(pos, vector.multiply(hdir, 0.4))
- local s = 9
- local g = -defense_mob_api.gravity
-
- local angle
- local delta = vector.subtract(obj:get_pos(), pos)
- local x2 = delta.x*delta.x + delta.z*delta.z
- if x2 == 0 then return end
- local s2 = s*s
- local r = s2*s2 - g * (g*x2 + 2*delta.y*s2)
- if r >= 0 then
- angle = math.atan((s2 + math.sqrt(r) * (math.random(0,1)*2-1))/(g*math.sqrt(x2)))
- else
- angle = math.pi/4
- end
-
- local xs = math.cos(angle) * s * (0.9 + math.random() * 0.2)
- local ys = math.sin(angle) * s * (0.9 + math.random() * 0.2)
- local horiz_angle = math.atan2(delta.z, delta.x) + (math.random() * 0.1 - 0.05)
- local v = {
- x = math.cos(horiz_angle) * xs,
- y = ys,
- z = math.sin(horiz_angle) * xs
- }
-
- local projectile = minetest.add_entity(pos, "mob_botete:gooball")
- projectile:setvelocity(v)
- self.object:setvelocity(vector.multiply(v, -0.4))
- self.automatic_face_movement_dir = false
- self.object:set_properties({automatic_face_movement_dir = self.automatic_face_movement_dir})
- if math.random() < 0.1 then
- self.attack_range = 4 + math.random() * 4
- end
- end,
- on_death = function(self)
- local pos = self.object:get_pos()
- for i=1,math.random(5,7) do
- local projectile = minetest.add_entity(pos, "mob_botete:gooball")
- projectile:setvelocity({
- x = -2 + math.random() * 4,
- y = -1 + math.random() * 4,
- z = -2 + math.random() * 4
- })
- end
- end,
- })
- minetest.register_entity("mob_botete:gooball", {
- physical = false,
- visual = "sprite",
- visual_size = {x=1, y=1},
- textures = {"mob_botete_gooball.png"},
- on_activate = function(self, staticdata)
- self.object:setacceleration({x=0, y=defense_mob_api.gravity, z=0})
- end,
- on_step = function(self, dtime)
- local pos = self.object:get_pos()
- local node = minetest.get_node(pos)
- if minetest.get_item_group(node.name, "caustic_goo") > 0 then
- self.object:remove()
- elseif node.name ~= "air" then
- local space = pos
- local nvel = vector.normalize(self.object:getvelocity())
- local back = vector.multiply(nvel, -1)
- local bnode
- repeat
- space = vector.add(space, back)
- bnode = minetest.get_node_or_nil(space)
- until not bnode or bnode.name == "air"
- place_goo(space, 8)
- self.object:remove()
- end
- end,
- })
- minetest.register_node("mob_botete:goo", {
- description = S("Caustic Goo"),
- tiles = {{
- name="mob_botete_goo.png",
- animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.7}
- }},
- inventory_image = "mob_botete_gooball.png",
- drawtype = "nodebox",
- node_box = {
- type = "fixed",
- fixed = {-0.5, -0.5, -0.5, 0.5, -0.5+2/16, 0.5},
- },
- selection_box = {
- type = "wallmounted",
- },
- paramtype = "light",
- paramtype2 = "wallmounted",
- liquid_viscosity = 4,
- liquidtype = "source",
- liquid_alternative_flowing = "mob_botete:goo",
- liquid_alternative_source = "mob_botete:goo",
- liquid_renewable = false,
- liquid_range = 0,
- groups = {caustic_goo=1, crumbly=3, dig_immediate=3, liquid=3, attached_node=1, disable_jump=1},
- drop = "",
- walkable = false,
- buildable_to = false,
- damage_per_second = 1,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(1 + math.random() * 4)
- end,
- on_timer = function(pos, elapsed)
- spread_goo(pos)
- return true
- end,
- })
- minetest.register_node("mob_botete:goo_block", {
- description = S("Caustic Goo Block"),
- tiles = {{
- name="mob_botete_goo.png",
- animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.7}
- }},
- drawtype = "allfaces",
- paramtype = "light",
- liquid_viscosity = 8,
- liquidtype = "source",
- liquid_alternative_flowing = "mob_botete:goo_block",
- liquid_alternative_source = "mob_botete:goo_block",
- liquid_renewable = false,
- liquid_range = 0,
- post_effect_color = {r=100, g=240, b=0, a=240},
- groups = {caustic_goo=1, crumbly=3, dig_immediate=3, liquid=3, falling_node=1, disable_jump=1},
- drop = "",
- walkable = false,
- buildable_to = false,
- damage_per_second = 1,
- on_construct = function(pos)
- minetest.get_node_timer(pos):start(0.5 + math.random() * 2)
- end,
- on_timer = function(pos, elapsed)
- spread_goo(pos)
- return true
- end,
- })
- minetest.register_alias("botete", "mob_boteete:botete")
|