mirror of
https://git.minetest.land/VoxeLibre/VoxeLibre.git
synced 2024-12-02 23:41:06 +01:00
0b27b6bec3
DO NOT USE IN PRODUCTION, DO NOT START OLD WORLDS WITHOUT A BACKUP These are the first steps of the new mob API. The game does actually start, but mobs do not work yet. You will also get some warnings about mob spawners, but don't worry about that. This is really just some 'first impression' of how the mob API is gonna look like. Some things are already complete, like the agression system. AI and attacking have not been worked on yet. mobs_mc and mcl_mobs have actually been merged into one piece but I will probably change that again in the future actually, and split the different mobs into different mods. There are also a few usefull things like the universal mount API and a more general purpose smoke API, but all of this is still far from complete. I'll put some work into the API this week but probably not next week, then I'll see but don't expect this to be done before 2022. I'll work on it, but I'll do it slowly and progressively to not get burned out again and to still have enough time to graduate from school in the meantime.
177 lines
5.9 KiB
Lua
177 lines
5.9 KiB
Lua
local S = minetest.get_translator("mcl_end")
|
|
|
|
local explosion_strength = 6
|
|
|
|
local directions = {
|
|
{x = 1}, {x = -1}, {z = 1}, {z = -1}
|
|
}
|
|
|
|
local dimensions = {"x", "y", "z"}
|
|
|
|
for _, dir in pairs(directions) do
|
|
for _, dim in pairs(dimensions) do
|
|
dir[dim] = dir[dim] or 0
|
|
end
|
|
end
|
|
|
|
local function find_crystal(pos)
|
|
local objects = minetest.get_objects_inside_radius(pos, 0)
|
|
for _, obj in pairs(objects) do
|
|
local luaentity = obj:get_luaentity()
|
|
if luaentity and luaentity.name == "mcl_end:crystal" then
|
|
return luaentity
|
|
end
|
|
end
|
|
end
|
|
|
|
local function crystal_explode(self, puncher)
|
|
if self._exploded then return end
|
|
self._exploded = true
|
|
local strength = 1
|
|
local source
|
|
if puncher then
|
|
strength = explosion_strength
|
|
local reason = {}
|
|
mcl_damage.from_punch(reason, puncher)
|
|
mcl_damage.finish_reason(reason)
|
|
source = reason.source
|
|
end
|
|
mcl_explosions.explode(vector.add(self.object:get_pos(), {x = 0, y = 1.5, z = 0}), strength, {drop_chance = 1}, self.object, source)
|
|
minetest.after(0, self.object.remove, self.object)
|
|
end
|
|
|
|
local function set_crystal_animation(self)
|
|
self.object:set_animation({x = 0, y = 120}, 25)
|
|
end
|
|
|
|
local function spawn_crystal(pos)
|
|
local crystal = minetest.add_entity(pos, "mcl_end:crystal")
|
|
if not vector.equals(pos, vector.floor(pos)) then return end
|
|
if mcl_worlds.pos_to_dimension(pos) ~= "end" then return end
|
|
local portal_center
|
|
for _, dir in pairs(directions) do
|
|
local node = minetest.get_node(vector.add(pos, dir))
|
|
if node.name == "mcl_portals:portal_end" then
|
|
portal_center = vector.add(pos, vector.multiply(dir, 3))
|
|
break
|
|
end
|
|
end
|
|
if not portal_center then return end
|
|
local crystals = {}
|
|
for i, dir in pairs(directions) do
|
|
local crystal_pos = vector.add(portal_center, vector.multiply(dir, 3))
|
|
crystals[i] = find_crystal(crystal_pos)
|
|
if not crystals[i] then return end
|
|
end
|
|
for _, crystal in pairs(crystals) do
|
|
crystal_explode(crystal)
|
|
end
|
|
local portal_pos = vector.add(portal_center, vector.new(-3, -1, -3))
|
|
mcl_structures.call_struct(portal_pos, "end_exit_portal")
|
|
minetest.add_entity(vector.add(portal_pos, vector.new(3, 11, 3)), "mcl_mobs:enderdragon"):get_luaentity()._portal_pos = portal_pos
|
|
end
|
|
|
|
minetest.register_entity("mcl_end:crystal", {
|
|
initial_properties = {
|
|
physical = true,
|
|
visual = "mesh",
|
|
visual_size = {x = 6, y = 6},
|
|
collisionbox = {-1, 0.5, -1, 1, 2.5, 1},
|
|
mesh = "mcl_end_crystal.b3d",
|
|
textures = {"mcl_end_crystal.png"},
|
|
collide_with_objects = false,
|
|
},
|
|
on_punch = crystal_explode,
|
|
on_activate = set_crystal_animation,
|
|
_exploded = false,
|
|
_hittable_by_projectile = true
|
|
})
|
|
|
|
minetest.register_entity("mcl_end:crystal_beam", {
|
|
initial_properties = {
|
|
physical = false,
|
|
visual = "cube",
|
|
visual_size = {x = 1, y = 1, z = 1},
|
|
textures = {
|
|
"mcl_end_crystal_beam.png^[transformR90",
|
|
"mcl_end_crystal_beam.png^[transformR90",
|
|
"mcl_end_crystal_beam.png",
|
|
"mcl_end_crystal_beam.png",
|
|
"blank.png",
|
|
"blank.png",
|
|
},
|
|
static_save = false,
|
|
},
|
|
spin = 0,
|
|
init = function(self, dragon, crystal)
|
|
self.dragon, self.crystal = dragon, crystal
|
|
crystal:get_luaentity().beam = self.object
|
|
dragon:get_luaentity().beam = self.object
|
|
end,
|
|
on_deactivate = function(self)
|
|
if self.crystal and self.crystal:get_luaentity() then
|
|
self.crystal:get_luaentity().beam = nil
|
|
end
|
|
if self.dragon and self.dragon:get_luaentity() then
|
|
self.dragon:get_luaentity().beam = nil
|
|
end
|
|
end,
|
|
on_step = function(self, dtime)
|
|
if self.dragon and self.dragon:get_luaentity() and self.crystal and self.crystal:get_luaentity() then
|
|
self.spin = self.spin + dtime * math.pi * 2 / 4
|
|
local dragon_pos, crystal_pos = self.dragon:get_pos(), self.crystal:get_pos()
|
|
|
|
dragon_pos.y = dragon_pos.y + 4
|
|
crystal_pos.y = crystal_pos.y + 2
|
|
|
|
self.object:set_pos(vector.divide(vector.add(dragon_pos, crystal_pos), 2))
|
|
local rot = vector.dir_to_rotation(vector.direction(dragon_pos, crystal_pos))
|
|
rot.z = self.spin
|
|
self.object:set_rotation(rot)
|
|
self.object:set_properties({visual_size = {x = 0.5, y = 0.5, z = vector.distance(dragon_pos, crystal_pos)}})
|
|
else
|
|
self.object:remove()
|
|
end
|
|
end,
|
|
})
|
|
|
|
minetest.register_craftitem("mcl_end:crystal", {
|
|
inventory_image = "mcl_end_crystal_item.png",
|
|
description = S("End Crystal"),
|
|
stack_max = 64,
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
if pointed_thing.type == "node" then
|
|
local pos = minetest.get_pointed_thing_position(pointed_thing)
|
|
local node = minetest.get_node(pos)
|
|
local node_name = node.name
|
|
if placer and not placer:get_player_control().sneak then
|
|
if minetest.registered_nodes[node_name] and minetest.registered_nodes[node_name].on_rightclick then
|
|
return minetest.registered_nodes[node_name].on_rightclick(pointed_thing.under, node, placer, itemstack) or itemstack
|
|
end
|
|
end
|
|
if find_crystal(pos) then return itemstack end
|
|
if node_name == "mcl_core:obsidian" or node_name == "mcl_core:bedrock" then
|
|
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
|
itemstack:take_item()
|
|
end
|
|
spawn_crystal(pos)
|
|
end
|
|
end
|
|
return itemstack
|
|
end,
|
|
_tt_help = S("Ignited by a punch or a hit with an arrow").."\n"..S("Explosion radius: @1", tostring(explosion_strength)),
|
|
_doc_items_longdesc = S("End Crystals are explosive devices. They can be placed on Obsidian or Bedrock. Ignite them by a punch or a hit with an arrow. End Crystals can also be used the spawn the Ender Dragon by placing one at each side of the End Exit Portal."),
|
|
_doc_items_usagehelp = S("Place the End Crystal on Obsidian or Bedrock, then punch it or hit it with an arrow to cause an huge and probably deadly explosion. To Spawn the Ender Dragon, place one at each side of the End Exit Portal."),
|
|
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = "mcl_end:crystal",
|
|
recipe = {
|
|
{"mcl_core:glass", "mcl_core:glass", "mcl_core:glass"},
|
|
{"mcl_core:glass", "mcl_end:ender_eye", "mcl_core:glass"},
|
|
{"mcl_core:glass", "mcl_mobitems:ghast_tear", "mcl_core:glass"},
|
|
}
|
|
})
|
|
|
|
minetest.register_alias("mcl_end_crystal:end_crystal", "mcl_end:crystal")
|