221 lines
7.2 KiB
Lua
221 lines
7.2 KiB
Lua
-- Include the player_api for animations
|
|
dofile(minetest.get_modpath("player_api") .. "/api.lua")
|
|
|
|
minetest.register_entity("practice_bot:bot", {
|
|
hp_max = 40,
|
|
physical = true,
|
|
collisionbox = {-0.3, 0, -0.3, 0.3, 1.7, 0.3},
|
|
visual = "mesh",
|
|
mesh = "character.b3d",
|
|
textures = {"character.png"},
|
|
animations = {
|
|
stand = {x = 0, y = 79},
|
|
walk = {x = 168, y = 187},
|
|
attack = {x = 189, y = 198},
|
|
},
|
|
animation_speed = 30,
|
|
current_animation = "stand",
|
|
attack_range = 20,
|
|
attack_damage = 2,
|
|
cooldown = 0.1,
|
|
last_attack_time = 0,
|
|
speed = 4,
|
|
bot_type = "easy",
|
|
set_animation = function(self, animation)
|
|
if self.current_animation ~= animation then
|
|
local anim = self.animations[animation]
|
|
if anim then
|
|
self.object:set_animation(anim, self.animation_speed, 0)
|
|
self.current_animation = animation
|
|
end
|
|
end
|
|
end,
|
|
|
|
on_step = function(self, dtime)
|
|
local pos = self.object:get_pos()
|
|
local velocity = self.object:get_velocity()
|
|
local players = minetest.get_connected_players()
|
|
local nearest_player = nil
|
|
local nearest_distance = self.attack_range
|
|
|
|
for _, player in ipairs(players) do
|
|
local player_pos = player:get_pos()
|
|
local distance = vector.distance(pos, player_pos)
|
|
|
|
if distance <= self.attack_range and distance < nearest_distance then
|
|
nearest_player = player
|
|
nearest_distance = distance
|
|
end
|
|
end
|
|
|
|
if not self.is_on_ground then
|
|
velocity.y = velocity.y - 9.8 * dtime
|
|
end
|
|
|
|
if nearest_player then
|
|
local player_pos = nearest_player:get_pos()
|
|
local distance = vector.distance(pos, player_pos)
|
|
|
|
local dir = vector.subtract(player_pos, pos)
|
|
dir.y = 0
|
|
local yaw = math.atan2(dir.z, dir.x) - math.pi / 2
|
|
self.object:set_yaw(yaw)
|
|
|
|
if distance > 1 then
|
|
self:set_animation("walk")
|
|
|
|
local new_velocity = vector.multiply(vector.normalize(dir), self.speed)
|
|
new_velocity.y = velocity.y
|
|
self.object:set_velocity(new_velocity)
|
|
else
|
|
local current_time = minetest.get_gametime()
|
|
if current_time - self.last_attack_time >= self.cooldown then
|
|
self:set_animation("attack")
|
|
nearest_player:punch(self.object, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy = self.attack_damage}})
|
|
self.last_attack_time = current_time
|
|
end
|
|
|
|
self.object:set_velocity({x = 0, y = velocity.y, z = 0})
|
|
end
|
|
else
|
|
self:set_animation("stand")
|
|
self.object:set_velocity({x = 0, y = velocity.y, z = 0})
|
|
end
|
|
|
|
local node_below = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
|
|
self.is_on_ground = node_below and minetest.registered_nodes[node_below.name] and minetest.registered_nodes[node_below.name].walkable
|
|
|
|
if self.is_on_ground and velocity.y == 0 then
|
|
local step_pos = vector.add(pos, vector.multiply(vector.normalize({x = velocity.x, y = 0, z = velocity.z}), 0.5))
|
|
step_pos.y = step_pos.y + 0.5
|
|
local step_node = minetest.get_node_or_nil(step_pos)
|
|
|
|
if step_node and minetest.registered_nodes[step_node.name] and minetest.registered_nodes[step_node.name].walkable then
|
|
self.object:set_velocity({x = velocity.x, y = 6, z = velocity.z})
|
|
end
|
|
end
|
|
end
|
|
|
|
})
|
|
|
|
local function spawn_practice_bot(pos, config)
|
|
local bot_pos = vector.add(pos, {x = 0, y = 1, z = 0})
|
|
local bot = minetest.add_entity(bot_pos, "practice_bot:bot")
|
|
if bot then
|
|
local bot_lua = bot:get_luaentity()
|
|
if bot_lua then
|
|
bot_lua.hp_max = config.hp_max
|
|
bot_lua.object:set_hp(config.hp_max)
|
|
bot_lua.speed = config.speed
|
|
bot_lua.attack_damage = config.attack_damage
|
|
bot_lua.cooldown = config.cooldown
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_tool("practice_bot:spawner_breaker", {
|
|
description = "Spawner Breaker Axe",
|
|
inventory_image = "spawner_breaker.png",
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.5,
|
|
max_drop_level = 1,
|
|
groupcaps = {
|
|
spawner_breakable = {times = {[1] = 1.0, [2] = 0.5, [3] = 0.2}, uses = 30, maxlevel = 3},
|
|
},
|
|
damage_groups = {fleshy = 5},
|
|
},
|
|
})
|
|
|
|
minetest.register_node("practice_bot:easy_spawner", {
|
|
description = "Easy Bot Spawner",
|
|
tiles = {"spawner_top.png", "easy_spawner_side.png"},
|
|
groups = {spawner_breakable = 1},
|
|
on_rightclick = function(pos)
|
|
spawn_practice_bot(pos, {
|
|
hp_max = 10,
|
|
speed = 2,
|
|
attack_damage = 1,
|
|
cooldown = 1.0
|
|
})
|
|
end
|
|
})
|
|
|
|
minetest.register_node("practice_bot:medium_spawner", {
|
|
description = "Medium Bot Spawner",
|
|
tiles = {"spawner_top.png", "medium_spawner_side.png"},
|
|
groups = {spawner_breakable = 1},
|
|
on_rightclick = function(pos)
|
|
spawn_practice_bot(pos, {
|
|
hp_max = 20,
|
|
speed = 3,
|
|
attack_damage = 2,
|
|
cooldown = 0.5
|
|
})
|
|
end
|
|
})
|
|
|
|
minetest.register_node("practice_bot:difficult_spawner", {
|
|
description = "Difficult Bot Spawner",
|
|
tiles = {"spawner_top.png", "hard_spawner_side.png"},
|
|
groups = {spawner_breakable = 1},
|
|
on_rightclick = function(pos)
|
|
spawn_practice_bot(pos, {
|
|
hp_max = 30,
|
|
speed = 5,
|
|
attack_damage = 4,
|
|
cooldown = 0.3
|
|
})
|
|
end
|
|
})
|
|
|
|
minetest.register_craftitem("practice_bot:easy_spawner_item", {
|
|
description = "Easy Bot Spawner Item",
|
|
inventory_image = "easy_spawner_side.png",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
if pointed_thing.under then
|
|
spawn_practice_bot(pointed_thing.under, {
|
|
hp_max = 10,
|
|
speed = 2,
|
|
attack_damage = 1,
|
|
cooldown = 1.0
|
|
})
|
|
itemstack:take_item()
|
|
end
|
|
return itemstack
|
|
end
|
|
})
|
|
|
|
minetest.register_craftitem("practice_bot:medium_spawner_item", {
|
|
description = "Medium Bot Spawner Item",
|
|
inventory_image = "medium_spawner_side.png",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
if pointed_thing.under then
|
|
spawn_practice_bot(pointed_thing.under, {
|
|
hp_max = 20,
|
|
speed = 3,
|
|
attack_damage = 2,
|
|
cooldown = 0.5
|
|
})
|
|
itemstack:take_item()
|
|
end
|
|
return itemstack
|
|
end
|
|
})
|
|
|
|
minetest.register_craftitem("practice_bot:difficult_spawner_item", {
|
|
description = "Difficult Bot Spawner Item",
|
|
inventory_image = "hard_spawner_side.png",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
if pointed_thing.under then
|
|
spawn_practice_bot(pointed_thing.under, {
|
|
hp_max = 30,
|
|
speed = 5,
|
|
attack_damage = 4,
|
|
cooldown = 0.3
|
|
})
|
|
itemstack:take_item()
|
|
end
|
|
return itemstack
|
|
end
|
|
})
|