diff --git a/README.txt b/README.txt index 91d300a..87c5f8e 100644 --- a/README.txt +++ b/README.txt @@ -59,7 +59,11 @@ This mod add some functions that you can use in other mods: lava_damage: the damage per second if the mob is in lava light_damage: the damage per second if the mob is in light on_rightclick: its same as in minetest.register_entity() -3. mobs:register_spawn(name, nodes, max_light, min_light, chance, mobs_per_30_block_radius) + attack_type: the attack type of a monster ("dogfight", "shoot", + maybe somehting like "explode" in the future (creeper)) + arrow: if the attack_type="shoot" needed: the entity name of the arrow + shoot_interval: the minimum shoot interval +2. mobs:register_spawn(name, nodes, max_light, min_light, chance, mobs_per_30_block_radius) This function adds the spawning of an animal (without it the registered animals and monster won't spawn!) "name" is the name of the animal/monster @@ -69,6 +73,17 @@ This mod add some functions that you can use in other mods: "chance" is same as in register_abm() "mobs_per_30_block_radius" is the maximum number of mobs in a 30 block radius arround the possible spawning pos +3. mobs:register_arrow(name, def) + "name" is the name of the arrow + "def" is a table with the following values: + visual: same is in minetest.register_entity() + visual_size: same is in minetest.register_entity() + textures: same is in minetest.register_entity() + velocity: the velocity of the arrow + hit_player: a function that is called when the arrow hits a player + params: (self, player) + hit_node: a function that is called when the arrow hits a node + params: (self, pos, node) License: Sourcecode: WTFPL (see below) diff --git a/api.lua b/api.lua index a6cba1b..738ea47 100644 --- a/api.lua +++ b/api.lua @@ -20,6 +20,9 @@ function mobs:register_mob(name, def) drawtype = def.drawtype, on_rightclick = def.on_rightclick, type = def.type, + attack_type = def.attack_type, + arrow = def.arrow, + shoot_interval = def.shoot_interval, timer = 0, attack = {player=nil, dist=nil}, @@ -160,7 +163,7 @@ function mobs:register_mob(name, def) v.y = 5 self.object:setvelocity(v) end - elseif self.state == "attack" then + elseif self.state == "attack" and self.attack_type == "dogfight" then local s = self.object:getpos() local p = self.attack.player:getpos() local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 @@ -220,6 +223,43 @@ function mobs:register_mob(name, def) }, vec) end end + elseif self.state == "attack" and self.attack_type == "shoot" then + local s = self.object:getpos() + local p = self.attack.player:getpos() + local dist = ((p.x-s.x)^2 + (p.y-s.y)^2 + (p.z-s.z)^2)^0.5 + if dist > self.view_range or self.attack.player:get_hp() <= 0 then + self.state = "stand" + self.v_start = false + self.set_velocity(self, 0) + self.attack = {player=nil, dist=nil} + return + else + self.attack.dist = dist + end + + local vec = {x=p.x-s.x, y=p.y-s.y, z=p.z-s.z} + local yaw = math.atan(vec.z/vec.x)+math.pi/2 + if self.drawtype == "side" then + yaw = yaw+(math.pi/2) + end + if p.x > s.x then + yaw = yaw+math.pi + end + self.object:setyaw(yaw) + self.set_velocity(self, 0) + + if self.timer > self.shoot_interval and math.random(1, 100) <= 60 then + self.timer = 0 + + local obj = minetest.env:add_entity(self.object:getpos(), self.arrow) + local amount = (vec.x^2+vec.y^2+vec.z^2)^0.5 + local v = obj:get_luaentity().velocity + vec.y = vec.y+1 + vec.x = vec.x*v/amount + vec.y = vec.y*v/amount + vec.z = vec.z*v/amount + obj:setvelocity(vec) + end end end, @@ -310,3 +350,32 @@ function mobs:register_spawn(name, nodes, max_light, min_light, chance, mobs_per end }) end + +function mobs:register_arrow(name, def) + minetest.register_entity(name, { + physical = false, + visual = def.visual, + visual_size = def.visual_size, + textures = def.textures, + velocity = def.velocity, + hit_player = def.hit_player, + hit_node = def.hit_node, + + on_step = function(self, dtime) + local pos = self.object:getpos() + if minetest.env:get_node(self.object:getpos()).name ~= "air" then + self.hit_node(self, pos, node) + self.object:remove() + return + end + pos.y = pos.y-1 + for _,player in pairs(minetest.env:get_objects_inside_radius(pos, 1)) do + if player:is_player() then + self.hit_player(self, player) + self.object:remove() + return + end + end + end + }) +end diff --git a/depends.txt b/depends.txt index 4ad96d5..70715c7 100644 --- a/depends.txt +++ b/depends.txt @@ -1 +1,2 @@ default +fire diff --git a/init.lua b/init.lua index 77588e4..9cb9caa 100644 --- a/init.lua +++ b/init.lua @@ -24,6 +24,7 @@ mobs:register_mob("mobs:dirt_monster", { lava_damage = 5, light_damage = 2, on_rightclick = nil, + attack_type = "dogfight", }) mobs:register_spawn("mobs:dirt_monster", {"default:dirt_with_grass"}, 3, -1, 5000, 5) @@ -51,6 +52,7 @@ mobs:register_mob("mobs:stone_monster", { water_damage = 0, lava_damage = 0, light_damage = 0, + attack_type = "dogfight", }) mobs:register_spawn("mobs:stone_monster", {"default:stone"}, 3, -1, 5000, 5) @@ -79,6 +81,7 @@ mobs:register_mob("mobs:sand_monster", { water_damage = 3, lava_damage = 1, light_damage = 0, + attack_type = "dogfight", }) mobs:register_spawn("mobs:sand_monster", {"default:desert_sand"}, 20, -1, 5000, 5) @@ -207,5 +210,84 @@ mobs:register_mob("mobs:oerkki", { water_damage = 1, lava_damage = 1, light_damage = 0, + attack_type = "dogfight", }) mobs:register_spawn("mobs:oerkki", {"default:stone"}, 2, -1, 5000, 5) + +mobs:register_mob("mobs:dungeon_master", { + type = "monster", + hp_max = 10, + collisionbox = {-0.8, -1.21875, -0.8, 0.8, 1.21875, 0.8}, + visual = "upright_sprite", + visual_size = {x=1.875, y=2.4375}, + textures = {"mobs_dungeon_master.png", "mobs_dungeon_master_back.png"}, + makes_footstep_sound = true, + view_range = 15, + walk_velocity = 1, + run_velocity = 3, + damage = 4, + drops = { + {name = "default:mese", + chance = 100, + min = 1, + max = 2,}, + }, + armor = 2, + drawtype = "front", + water_damage = 1, + lava_damage = 1, + light_damage = 0, + on_rightclick = nil, + attack_type = "shoot", + arrow = "mobs:fireball", + shoot_interval = 2.5, +}) +mobs:register_spawn("mobs:dungeon_master", {"default:stone"}, 2, -1, 5000, 0) + +mobs:register_arrow("mobs:fireball", { + visual = "sprite", + visual_size = {x=1, y=1}, + --textures = {{name="mobs_fireball.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=0.5}}}, FIXME + textures = {"mobs_fireball.png"}, + velocity = 5, + hit_player = function(self, player) + local s = self.object:getpos() + local p = player:getpos() + local vec = {x=s.x-p.x, y=s.y-p.y, z=s.z-p.z} + player:punch(self.object, 1.0, { + full_punch_interval=1.0, + groupcaps={ + fleshy={times={[1]=1/2, [2]=1/3, [3]=1/4}}, + } + }, vec) + local pos = self.object:getpos() + for dx=-1,1 do + for dy=-1,1 do + for dz=-1,1 do + local p = {x=pos.x+dx, y=pos.y+dy, z=pos.z+dz} + local n = minetest.env:get_node(pos).name + if minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 30 then + minetest.env:set_node(p, {name="fire:basic_flame"}) + else + minetest.env:remove_node(p) + end + end + end + end + end, + hit_node = function(self, pos, node) + for dx=-1,1 do + for dy=-2,1 do + for dz=-1,1 do + local p = {x=pos.x+dx, y=pos.y+dy, z=pos.z+dz} + local n = minetest.env:get_node(pos).name + if minetest.registered_nodes[n].groups.flammable or math.random(1, 100) <= 30 then + minetest.env:set_node(p, {name="fire:basic_flame"}) + else + minetest.env:remove_node(p) + end + end + end + end + end +}) diff --git a/textures/mobs_dungeon_master.png b/textures/mobs_dungeon_master.png new file mode 100644 index 0000000..059131d Binary files /dev/null and b/textures/mobs_dungeon_master.png differ diff --git a/textures/mobs_dungeon_master_back.png b/textures/mobs_dungeon_master_back.png new file mode 100644 index 0000000..e7b551e Binary files /dev/null and b/textures/mobs_dungeon_master_back.png differ diff --git a/textures/mobs_fireball.png b/textures/mobs_fireball.png new file mode 100644 index 0000000..1ca4522 Binary files /dev/null and b/textures/mobs_fireball.png differ diff --git a/textures/mobs_fireball_animated.png b/textures/mobs_fireball_animated.png new file mode 100644 index 0000000..cc556d1 Binary files /dev/null and b/textures/mobs_fireball_animated.png differ