This commit is contained in:
Lizzy Fleckenstein 2020-10-27 16:37:40 +01:00
commit 64e62486e2
32 changed files with 350 additions and 210 deletions

View File

@ -203,7 +203,8 @@ There are so many people to list (sorry). Check out the respective mod directori
* [ryvnf](https://github.com/ryvnf): Explosion mechanics * [ryvnf](https://github.com/ryvnf): Explosion mechanics
* MysticTempest: Bugfixes * MysticTempest: Bugfixes
* [bzoss](https://github.com/bzoss): Status effects, potions, brewing stand * [bzoss](https://github.com/bzoss): Status effects, potions, brewing stand
* kay27 <kay27@bk.ru>: Bugfixes, optimizations * kay27 <kay27@bk.ru>: Experience system, bugfixes, optimizations
* 2mac: Fix bug with powered rail
* Lots of other people: TO BE WRITTEN (see mod directories for details) * Lots of other people: TO BE WRITTEN (see mod directories for details)
#### Mod credits (summary) #### Mod credits (summary)

View File

@ -70,6 +70,12 @@ function mcl_worlds.has_weather(pos)
return pos.y <= mcl_vars.mg_overworld_max and pos.y >= mcl_vars.mg_overworld_min - 64 return pos.y <= mcl_vars.mg_overworld_max and pos.y >= mcl_vars.mg_overworld_min - 64
end end
-- Takes a position and returns true if this position can have Nether dust
function mcl_worlds.has_dust(pos)
-- Weather in the Overworld and the high part of the void below
return pos.y <= mcl_vars.mg_nether_max + 64 and pos.y >= mcl_vars.mg_nether_min - 64
end
-- Takes a position (pos) and returns true if compasses are working here -- Takes a position (pos) and returns true if compasses are working here
function mcl_worlds.compass_works(pos) function mcl_worlds.compass_works(pos)
-- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below -- It doesn't work in Nether and the End, but it works in the Overworld and in the high part of the void below

View File

@ -414,14 +414,17 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
-- Slow down or speed up -- Slow down or speed up
local acc = dir.y * -1.8 local acc = dir.y * -1.8
local friction = 0.4
local speed_mod = minetest.registered_nodes[minetest.get_node(pos).name]._rail_acceleration local speed_mod = minetest.registered_nodes[minetest.get_node(pos).name]._rail_acceleration
acc = acc - friction
if has_fuel then if has_fuel then
acc = acc + 0.2 acc = acc + 0.6
elseif speed_mod and speed_mod ~= 0 then end
acc = acc + speed_mod
else if speed_mod and speed_mod ~= 0 then
acc = acc - 0.4 acc = acc + speed_mod + friction
end end
new_acc = vector.multiply(dir, acc) new_acc = vector.multiply(dir, acc)

View File

@ -39,12 +39,6 @@ mobs:register_mob("mobs_mc:enderdragon", {
dogshoot_count2_max = 5, dogshoot_count2_max = 5,
passive = false, passive = false,
attack_animals = true, attack_animals = true,
drops = {
{name = mobs_mc.items.dragon_egg,
chance = 1,
min = 1,
max = 1},
},
lava_damage = 0, lava_damage = 0,
fire_damage = 0, fire_damage = 0,
on_rightclick = nil, on_rightclick = nil,
@ -58,8 +52,17 @@ mobs:register_mob("mobs_mc:enderdragon", {
walk_start = 0, walk_end = 20, walk_start = 0, walk_end = 20,
run_start = 0, run_end = 20, run_start = 0, run_end = 20,
}, },
ignores_nametag = true, ignores_nametag = true,
on_die = function(self, own_pos)
if self._egg_spawn_pos then
local pos = minetest.string_to_pos(self._egg_spawn_pos)
--if minetest.get_node(pos).buildable_to then
minetest.set_node(pos, {name = mobs_mc.items.dragon_egg})
return
--end
end
minetest.add_item(own_pos, mobs_mc.items.dragon_egg)
end
}) })

View File

@ -10,6 +10,7 @@ end
dofile(modpath.."/weather_core.lua") dofile(modpath.."/weather_core.lua")
dofile(modpath.."/snow.lua") dofile(modpath.."/snow.lua")
dofile(modpath.."/rain.lua") dofile(modpath.."/rain.lua")
dofile(modpath.."/nether_dust.lua")
if minetest.get_modpath("lightning") ~= nil then if minetest.get_modpath("lightning") ~= nil then
dofile(modpath.."/thunder.lua") dofile(modpath.."/thunder.lua")

View File

@ -0,0 +1,39 @@
mcl_weather.nether_dust = {}
mcl_weather.nether_dust.particles_count = 99
-- calculates coordinates and draw particles for Nether dust
mcl_weather.nether_dust.add_dust_particles = function(player)
for i=mcl_weather.nether_dust.particles_count, 1,-1 do
local rpx, rpy, rpz = mcl_weather.get_random_pos_by_player_look_dir(player)
minetest.add_particle({
pos = {x = rpx, y = rpy - math.random(6, 18), z = rpz},
velocity = {x = math.random(-30,30)*0.01, y = math.random(-15,15)*0.01, z = math.random(-30,30)*0.01},
acceleration = {x = math.random(-50,50)*0.02, y = math.random(-20,20)*0.02, z = math.random(-50,50)*0.02},
expirationtime = 3,
size = math.random(6,20)*0.01,
collisiondetection = false,
object_collision = false,
vertical = false,
glow = math.random(0,minetest.LIGHT_MAX),
texture = "mcl_particles_nether_dust"..tostring(i%3+1)..".png",
playername = player:get_player_name()
})
end
end
local timer = 0
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= 0.7 then
timer = 0
else
return
end
for _, player in ipairs(minetest.get_connected_players()) do
if not mcl_worlds.has_dust(player:get_pos()) then
return false
end
mcl_weather.nether_dust.add_dust_particles(player)
end
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

View File

@ -2,6 +2,8 @@ local S = minetest.get_translator("mcl_experience")
mcl_experience = {} mcl_experience = {}
local pool = {} local pool = {}
local registered_nodes local registered_nodes
local max_xp = 2^31-1
local max_orb_age = 300 -- seconds
local gravity = {x = 0, y = -((tonumber(minetest.settings:get("movement_gravity"))) or 9.81), z = 0} local gravity = {x = 0, y = -((tonumber(minetest.settings:get("movement_gravity"))) or 9.81), z = 0}
local size_min, size_max = 20, 59 -- percents local size_min, size_max = 20, 59 -- percents
@ -45,7 +47,7 @@ end
-- saves data to be utilized on next login -- saves data to be utilized on next login
local save_data = function(player) local save_data = function(player)
name = player:get_player_name() local name = player:get_player_name()
local temp_pool = pool[name] local temp_pool = pool[name]
local meta = player:get_meta() local meta = player:get_meta()
meta:set_int("xp", temp_pool.xp) meta:set_int("xp", temp_pool.xp)
@ -68,10 +70,13 @@ hud_manager.add_hud = function(player,hud_name,def)
hud_elem_type = def.hud_elem_type, hud_elem_type = def.hud_elem_type,
position = def.position, position = def.position,
text = def.text, text = def.text,
text2 = def.text2,
number = def.number, number = def.number,
item = def.item,
direction = def.direction, direction = def.direction,
size = def.size, size = def.size,
offset = def.offset, offset = def.offset,
z_index = def.z_index,
}) })
-- create new 3d array here -- create new 3d array here
-- depends.txt is not needed -- depends.txt is not needed
@ -143,9 +148,8 @@ function mcl_experience.set_player_xp_level(player,level)
return return
end end
pool[name].level = level pool[name].level = level
pool[name].xp, pool[name].next_level = mcl_experience.bar_to_xp(pool[name].bar, level) pool[name].xp, pool[name].bar_step, pool[name].next_level = mcl_experience.bar_to_xp(pool[name].bar, level)
hud_manager.change_hud({player = player, hud_name = "xp_level_fg", element = "text", data = tostring(level)}) hud_manager.change_hud({player = player, hud_name = "xp_level", element = "text", data = tostring(level)})
hud_manager.change_hud({player = player, hud_name = "xp_level_bg", element = "text", data = tostring(level)})
-- we may don't update the bar -- we may don't update the bar
end end
@ -158,40 +162,25 @@ minetest.register_on_joinplayer(function(player)
name = player:get_player_name() name = player:get_player_name()
temp_pool = pool[name] temp_pool = pool[name]
hud_manager.add_hud(player, "experience_bar_background",
{
hud_elem_type = "statbar", position = {x=0.5, y=1},
name = "experience bar background", text = "experience_bar_background.png",
number = 36, direction = 0,
offset = {x = (-8 * 28) - 29, y = -(48 + 24 + 16)},
size = { x=28, y=28 }, z_index = 3,
})
hud_manager.add_hud(player,"experience_bar", hud_manager.add_hud(player,"experience_bar",
{ {
hud_elem_type = "statbar", position = {x=0.5, y=1}, hud_elem_type = "statbar", position = {x=0.5, y=1},
name = "experience bar", text = "experience_bar.png", name = "experience bar",
number = temp_pool.bar, direction = 0, text = "experience_bar.png",
text2 = "experience_bar_background.png",
number = temp_pool.bar, item = 36,
direction = 0,
offset = {x = (-8 * 28) - 29, y = -(48 + 24 + 16)}, offset = {x = (-8 * 28) - 29, y = -(48 + 24 + 16)},
size = { x=28, y=28 }, z_index = 4, size = { x=28, y=28 }, z_index = 11,
}) })
hud_manager.add_hud(player,"xp_level_bg", hud_manager.add_hud(player,"xp_level",
{ {
hud_elem_type = "text", position = {x=0.5, y=1}, hud_elem_type = "text", position = {x=0.5, y=1},
name = "xp_level_bg", text = tostring(temp_pool.level), name = "xp_level", text = tostring(temp_pool.level),
number = 0x000000,
offset = {x = 0, y = -(48 + 24 + 24)},
z_index = 5,
})
hud_manager.add_hud(player,"xp_level_fg",
{
hud_elem_type = "text", position = {x=0.5, y=1},
name = "xp_level_fg", text = tostring(temp_pool.level),
number = 0xFFFFFF, number = 0xFFFFFF,
offset = {x = -1, y = -(48 + 24 + 25)}, offset = {x = 0, y = -(48 + 24 + 24)},
z_index = 6, z_index = 12,
}) })
end) end)
@ -248,29 +237,32 @@ function mcl_experience.add_experience(player, experience)
local temp_pool = pool[name] local temp_pool = pool[name]
local old_bar, old_xp, old_level = temp_pool.bar, temp_pool.xp, temp_pool.level local old_bar, old_xp, old_level = temp_pool.bar, temp_pool.xp, temp_pool.level
temp_pool.xp = math.max(temp_pool.xp + experience, 0) temp_pool.xp = math.min(math.max(temp_pool.xp + experience, 0), max_xp)
if (temp_pool.xp >= temp_pool.xp_next_level) or (experience < 1) then
if (temp_pool.xp < temp_pool.xp_next_level) and (temp_pool.xp >= old_xp) then
temp_pool.bar = temp_pool.bar + temp_pool.bar_step * experience
else
temp_pool.level = mcl_experience.xp_to_level(temp_pool.xp) temp_pool.level = mcl_experience.xp_to_level(temp_pool.xp)
temp_pool.bar, temp_pool.bar_step, temp_pool.xp_next_level = mcl_experience.xp_to_bar(temp_pool.xp, temp_pool.level) temp_pool.bar, temp_pool.bar_step, temp_pool.xp_next_level = mcl_experience.xp_to_bar(temp_pool.xp, temp_pool.level)
if old_level ~= temp_pool.level then
if minetest.get_us_time()/1000000 - temp_pool.last_time > 0.04 then
minetest.sound_play("level_up",{gain=0.2,to_player = name})
temp_pool.last_time = minetest.get_us_time()/1000000
end
hud_manager.change_hud({player = player, hud_name = "xp_level_fg", element = "text", data = tostring(temp_pool.level)})
hud_manager.change_hud({player = player, hud_name = "xp_level_bg", element = "text", data = tostring(temp_pool.level)})
end
else
if minetest.get_us_time()/1000000 - temp_pool.last_time > 0.01 then
temp_pool.last_time = minetest.get_us_time()/1000000
minetest.sound_play("experience",{gain=0.1,to_player = name,pitch=math.random(75,99)/100})
end
temp_pool.bar = temp_pool.bar + temp_pool.bar_step * experience
end end
if old_bar ~= temp_pool.bar then if old_bar ~= temp_pool.bar then
hud_manager.change_hud({player = player, hud_name = "experience_bar", element = "number", data = math.floor(temp_pool.bar)}) hud_manager.change_hud({player = player, hud_name = "experience_bar", element = "number", data = math.floor(temp_pool.bar)})
end end
if experience > 0 and minetest.get_us_time()/1000000 - temp_pool.last_time > 0.01 then
if old_level ~= temp_pool.level then
minetest.sound_play("level_up",{gain=0.2,to_player = name})
temp_pool.last_time = minetest.get_us_time()/1000000 + 0.2
else
minetest.sound_play("experience",{gain=0.1,to_player = name,pitch=math.random(75,99)/100})
temp_pool.last_time = minetest.get_us_time()/1000000
end
end
if old_level ~= temp_pool.level then
hud_manager.change_hud({player = player, hud_name = "xp_level", element = "text", data = tostring(temp_pool.level)})
end
end end
--reset player level --reset player level
@ -290,8 +282,7 @@ minetest.register_on_dieplayer(function(player)
temp_pool.level = 0 temp_pool.level = 0
temp_pool.xp = 0 temp_pool.xp = 0
hud_manager.change_hud({player = player, hud_name = "xp_level_fg", element = "text", data = tostring(temp_pool.level)}) hud_manager.change_hud({player = player, hud_name = "xp_level", element = "text", data = tostring(temp_pool.level)})
hud_manager.change_hud({player = player, hud_name = "xp_level_bg", element = "text", data = tostring(temp_pool.level)})
hud_manager.change_hud({player = player, hud_name = "experience_bar", element = "number", data = math.floor(temp_pool.bar)}) hud_manager.change_hud({player = player, hud_name = "experience_bar", element = "number", data = math.floor(temp_pool.bar)})
mcl_experience.throw_experience(player:get_pos(), xp_amount) mcl_experience.throw_experience(player:get_pos(), xp_amount)
@ -352,7 +343,7 @@ local function xp_step(self, dtime)
self.age = self.age + dtime self.age = self.age + dtime
if self.age > 300 then if self.age > max_orb_age then
self.object:remove() self.object:remove()
return return
end end
@ -491,8 +482,8 @@ minetest.register_entity("mcl_experience:orb", {
}) })
minetest.register_chatcommand("xp", { minetest.register_chatcommand("xp", {
params = S("[<player>] [<xp>]"), params = S("[[<player>] <xp>]"),
description = S("Gives [[player <player>] <xp>] XP"), description = S("Gives a player some XP"),
privs = {server=true}, privs = {server=true},
func = function(name, params) func = function(name, params)
local player, xp = nil, 1000 local player, xp = nil, 1000
@ -521,7 +512,6 @@ minetest.register_chatcommand("xp", {
end end
mcl_experience.add_experience(player, xp) mcl_experience.add_experience(player, xp)
local playername = player:get_player_name() local playername = player:get_player_name()
-- minetest.chat_send_player(name, "Added " .. tostring(xp) .. " XP to " .. playername .. ", they've got " .. tostring(pool[playername].xp) .. " XP, level " .. tostring(pool[playername].level))
minetest.chat_send_player(name, S("Added @1 XP to @2, total: @3, experience level: @4", tostring(xp), playername, tostring(pool[playername].xp), tostring(pool[playername].level))) minetest.chat_send_player(name, S("Added @1 XP to @2, total: @3, experience level: @4", tostring(xp), playername, tostring(pool[playername].xp), tostring(pool[playername].level)))
end, end,
}) })

View File

@ -1,5 +1,5 @@
[<player>] [<xp>]=[<игрок>] [<xp>] [[<player>] <xp>]=[[<игрок>] <xp>]
Gives [[player <player>] <xp>] XP=Даёт [[игроку <игрок> [<xp>]] единиц опыта XP Gives a player some XP=Даёт игроку XP
Error: Too many parameters!=Ошибка: слишком много параметров! Error: Too many parameters!=Ошибка: слишком много параметров!
Error: Incorrect value of XP=Ошибка: Недопустимое значение XP Error: Incorrect value of XP=Ошибка: Недопустимое значение XP
Error: Player not found=Ошибка: Игрок не найден Error: Player not found=Ошибка: Игрок не найден

View File

@ -1,5 +1,5 @@
[<player>] [<xp>]= [[<player>] <xp>]=
Gives [[player <player>] <xp>] XP= Gives a player some XP=
Error: Too many parameters!= Error: Too many parameters!=
Error: Incorrect value of XP= Error: Incorrect value of XP=
Error: Player not found= Error: Player not found=

View File

@ -197,7 +197,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
if obj ~= self._shooter and obj:is_player() then if obj ~= self._shooter and obj:is_player() then
ok = true ok = true
elseif obj:get_luaentity() ~= nil then elseif obj:get_luaentity() ~= nil then
if obj ~= self._shooter and obj:get_luaentity()._cmi_is_mob then if obj ~= self._shooter and (obj:get_luaentity()._cmi_is_mob or obj:get_luaentity()._hittable_by_projectile) then
ok = true ok = true
end end
end end
@ -219,7 +219,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
local obj = closest_object local obj = closest_object
local is_player = obj:is_player() local is_player = obj:is_player()
local lua = obj:get_luaentity() local lua = obj:get_luaentity()
if obj ~= self._shooter and (is_player or (lua and lua._cmi_is_mob)) then if obj ~= self._shooter and (is_player or (lua and (lua._cmi_is_mob or lua._hittable_by_projectile))) then
if obj:get_hp() > 0 then if obj:get_hp() > 0 then
-- Check if there is no solid node between arrow and object -- Check if there is no solid node between arrow and object
local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true) local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 B

After

Width:  |  Height:  |  Size: 324 B

View File

@ -0,0 +1,114 @@
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 = puncher and explosion_strength or 1
mcl_explosions.explode(vector.add(self.object:get_pos(), {x = 0, y = 1.5, z = 0}), strength, {drop_chance = 1}, puncher)
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 dragon = minetest.add_entity(vector.add(portal_center, {x = 0, y = 10, z = 0}), "mobs_mc:enderdragon")
dragon:get_luaentity()._egg_spawn_pos = minetest.pos_to_string(vector.add(portal_center, {x = 0, y = 4, z = 0}))
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 = true,
},
on_punch = crystal_explode,
on_activate = set_crystal_animation,
_exploded = false,
_hittable_by_projectile = true
})
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).name
if find_crystal(pos) then return itemstack end
if node == "mcl_core:obsidian" or node == "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")

View File

@ -4,3 +4,6 @@ local basepath = minetest.get_modpath(minetest.get_current_modname())
dofile(basepath.."/chorus_plant.lua") dofile(basepath.."/chorus_plant.lua")
dofile(basepath.."/building.lua") dofile(basepath.."/building.lua")
dofile(basepath.."/eye_of_ender.lua") dofile(basepath.."/eye_of_ender.lua")
if not minetest.get_modpath("mcl_end_crystal") then
dofile(basepath.."/end_crystal.lua")
end

View File

@ -26,3 +26,8 @@ The stem attaches itself to end stone and other chorus blocks.=Der Stängel muss
Grows on end stone=Wächst auf Endstein Grows on end stone=Wächst auf Endstein
Randomly teleports you when eaten=Zufällige Teleportation, wenn gegessen Randomly teleports you when eaten=Zufällige Teleportation, wenn gegessen
Guides the way to the mysterious End dimension=Weist den Weg zur mysteriösen Endedimension Guides the way to the mysterious End dimension=Weist den Weg zur mysteriösen Endedimension
End Crystal=Enderkristall
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.=Enderkristalle sind explosiv. Sie können auf Obsidian oder Grundgestein platziert werden. Man kann sie durch einen Schlag oder einen Treffer mit einem Pfeil entzünden. Außerdem können sie benutzt werden, um den Enderdrachen zu erzeugen, in dem man je einen auf jeder Seite des Endausgangsportals platziert.
Explosion radius: @1=Explosionsradius: @1
Ignited by a punch or a hit with an arrow=Entzündbar durch einen Schlag oder einen Treffer mit einem Pfeil
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.=Enderkistall auf Obsidian oder Grundgestein platzieren, dann Enderkristall schlagen oder mit einem Pfeil treffen. Dies bewirkt eine riesige und meistens tödliche Explosion.

View File

@ -26,3 +26,8 @@ The stem attaches itself to end stone and other chorus blocks.=
Grows on end stone= Grows on end stone=
Randomly teleports you when eaten= Randomly teleports you when eaten=
Guides the way to the mysterious End dimension= Guides the way to the mysterious End dimension=
End Crystal=
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.=
Explosion radius: @1=
Ignited by a punch or a hit with an arrow=
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.=

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 561 B

View File

@ -157,7 +157,7 @@ local check_object_hit = function(self, pos, dmg)
-- TODO: Deal knockback -- TODO: Deal knockback
self.object:remove() self.object:remove()
return true return true
elseif entity._cmi_is_mob == true and (self._thrower ~= object) then elseif (entity._cmi_is_mob == true or entity._hittable_by_projectile) and (self._thrower ~= object) then
-- FIXME: Knockback is broken -- FIXME: Knockback is broken
object:punch(self.object, 1.0, { object:punch(self.object, 1.0, {
full_punch_interval = 1.0, full_punch_interval = 1.0,
@ -196,22 +196,24 @@ end
local snowball_on_step = function(self, dtime) local snowball_on_step = function(self, dtime)
self.timer=self.timer+dtime self.timer=self.timer+dtime
local pos = self.object:get_pos() local pos = self.object:get_pos()
local vel = self.object:get_velocity()
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local def = minetest.registered_nodes[node.name] local def = minetest.registered_nodes[node.name]
-- Destroy when hitting a solid node -- Destroy when hitting a solid node
if self._lastpos.x~=nil then if self._lastpos.x~=nil then
if (def and def.walkable) or not def then if (def and def.walkable) or not def then
minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = self.object:get_pos(), max_hear_distance=16, gain=0.7 }, true) minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
snowball_particles(self._lastpos, self.object:get_velocity()) snowball_particles(self._lastpos, vel)
self.object:remove() self.object:remove()
return return
end end
end end
if check_object_hit(self, pos, {snowball_vulnerable = 3}) then if check_object_hit(self, pos, {snowball_vulnerable = 3}) then
minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = self.object:get_pos(), max_hear_distance=16, gain=0.7 }, true) minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
snowball_particles(pos, self.object:get_velocity()) snowball_particles(pos, vel)
self.object:remove() self.object:remove()
return return
end end

View File

@ -1,102 +0,0 @@
--[[
swiftness - how fast you mine
hardness - allows the tool to go way above it's level
durable - makes the tool last longer
slippery - you drop the tool randomly
careful - "not silk touch"
fortune - drops extra items and experience
autorepair - tool will repair itself randomly
spiky - the tool will randomly hurt you when used
sharpness - the tool does more damage
]]--
local S = minetest.get_translator("mcl_tools")
local enchantment_list = {"swiftness", "durable", "careful", "fortune", "autorepair", "sharpness"}
local hexer = {"a","b","c","d","e","f","1","2","3","4","5","6","7","8","9","0"}
minetest.register_node("mcl_tools:enchantingtable", {
description = S("Enchanting Table"),
tiles = {"mcl_core_bedrock.png"},
groups = {wood = 1, pathable = 1},
sounds = mcl_sounds.node_sound_stone_defaults(),
is_ground_content = false,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
minetest.after(0,function(clicker)
local stack = clicker:get_wielded_item()
local meta = stack:get_meta()
if meta:get_string("enchanted") == "true" then return end
if not minetest.registered_tools[itemstack:get_name()] then return end
local tool_caps = itemstack:get_tool_capabilities()
local groupcaps = tool_caps.groupcaps
if not groupcaps then return end
local able_enchantments = table.copy(enchantment_list)
local player_level = mcl_experience.get_player_xp_level(clicker)
local enchants_available = math.floor(player_level/5)
local max_enchant_level = math.floor(player_level/5)
if enchants_available <= 0 then return end
if enchants_available > 3 then enchants_available = 3 end
local stock_name = minetest.registered_tools[stack:get_name()].name
local description = minetest.registered_tools[stack:get_name()].description
for i = 1,enchants_available do
local new_enchant = enchantment_list[math.random(1,table.getn(enchantment_list))]
local level = math.random(1,max_enchant_level)
if meta:get_int(new_enchant) == 0 then
player_level = player_level - 5
meta:set_int(new_enchant, level)
description = description.."\n"..new_enchant:gsub("^%l", string.upper)..": "..tostring(level)
if new_enchant == "swiftness" then
for index,table in pairs(groupcaps) do
for index2,time in pairs(table.times) do
tool_caps["groupcaps"][index]["times"][index2] = time/(level+1)
end
end
end
if new_enchant == "durable" then
for index,table in pairs(groupcaps) do
tool_caps["groupcaps"][index]["uses"] = table.uses*(level+1)
end
end
if new_enchant == "sharpness" then
for index,data in pairs(tool_caps.damage_groups) do
tool_caps.damage_groups[index] = data*(level+1)
end
end
end
end
meta:set_string("description", S("Enchanted @1", description))
meta:set_string("enchanted", "true")
meta:set_tool_capabilities(tool_caps)
mcl_experience.set_player_xp_level(clicker,player_level)
--create truly random hex
local colorstring = "#"
for i = 1,6 do
colorstring = colorstring..hexer[math.random(1,16)]
end
stack = minetest.itemstring_with_color(stack, colorstring)
clicker:set_wielded_item(stack)
end,clicker)
end
})
minetest.register_craft({
output = "mcl_tools:enchantingtable",
recipe = {
{"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"},
{"mcl_core:obsidian", "mcl_core:diamond", "mcl_core:obsidian"},
{"mcl_core:obsidian", "mcl_core:obsidian", "mcl_core:obsidian"},
},
})

View File

@ -592,4 +592,3 @@ minetest.register_tool("mcl_tools:shears", {
dofile(minetest.get_modpath("mcl_tools").."/crafting.lua") dofile(minetest.get_modpath("mcl_tools").."/crafting.lua")
dofile(minetest.get_modpath("mcl_tools").."/aliases.lua") dofile(minetest.get_modpath("mcl_tools").."/aliases.lua")
dofile(minetest.get_modpath("mcl_tools").."/enchanting.lua")

View File

@ -30,5 +30,3 @@ Iron Sword=Eisenschwert
Golden Sword=Goldschwert Golden Sword=Goldschwert
Diamond Sword=Diamantschwert Diamond Sword=Diamantschwert
Shears=Schere Shears=Schere
Enchanted @1=
Enchanting Table=

View File

@ -30,5 +30,3 @@ Iron Sword=Espada de hierro
Golden Sword=Espada de oro Golden Sword=Espada de oro
Diamond Sword=Espada de diamante Diamond Sword=Espada de diamante
Shears=Tijeras Shears=Tijeras
Enchanted @1=
Enchanting Table=

View File

@ -30,5 +30,3 @@ Iron Sword=Épée en Fer
Golden Sword=Épée en Or Golden Sword=Épée en Or
Diamond Sword=Épée en Diamant Diamond Sword=Épée en Diamant
Shears=Cisailles Shears=Cisailles
Enchanted @1=
Enchanting Table=

View File

@ -30,5 +30,3 @@ Iron Sword=Железный меч
Golden Sword=Золотой меч Golden Sword=Золотой меч
Diamond Sword=Алмазный меч Diamond Sword=Алмазный меч
Shears=Ножницы Shears=Ножницы
Enchanted @1=@1 зачарованный(ая)
Enchanting Table=Волшебный стол

View File

@ -30,5 +30,3 @@ Iron Sword=
Golden Sword= Golden Sword=
Diamond Sword= Diamond Sword=
Shears= Shears=
Enchanted @1=
Enchanting Table=

View File

@ -1,7 +1,44 @@
import png import png
w, h = 64, 256; w, h = 16, 128;
s = [[int(0) for c in range(w)] for c in range(h)] s = [[int(0) for c in range(w)] for c in range(h)]
def drawpixel(x, y, t):
if (x >= 0) and (x < w) and (y >= 0) and (y < h):
if(t == 1):
s[y][x] = 1
elif t==2:
s[y][x] = 1 - s[y][x]
elif t==3:
s[y][x] = s[y][x] + 1
if s[y][x] > 3:
s[y][x] =s[y][x]-4
def circle(X1, Y1, R, t):
x = 0
y = R
delta = 1 - 2 * R
error = 0
while y >= 0:
if Y1%w + y < w:
drawpixel(X1 + x, Y1 + y, t)
if Y1%w - y >= 0:
drawpixel(X1 + x, Y1 - y, t)
if Y1%w + y < w:
drawpixel(X1 - x, Y1 + y, t)
if Y1%w - y >= 0:
drawpixel(X1 - x, Y1 - y, t)
error = 2 * (delta + y) - 1
if ((delta < 0) and (error <= 0)):
x = x + 1
delta = delta + 2 * x + 1
elif ((delta > 0) and (error > 0)):
y = y - 1
delta = delta - 2 * y + 1
else:
x = x + 1
y = y - 1
delta = delta + 2 * (x - y)
def line(y1, x1, y2, x2, v): def line(y1, x1, y2, x2, v):
signx = 1 signx = 1
signy = 1 signy = 1
@ -19,10 +56,14 @@ def line(y1, x1, y2, x2, v):
if dx >= dy: if dx >= dy:
dir1 = 1 dir1 = 1
for i in range(max(dx, dy)+1): for i in range(max(dx, dy)+1):
if v==2: if(v == 1):
s[x1][y1]=1-s[x1][y1] s[x1][y1] = 1
else: elif v==2:
s[x1][y1] = v s[x1][y1] = 1 - s[x1][y1]
elif v==3 or (v==4 and ((x1^y1)&1)) or (v==5 and (((x1|y1)&1)==0)) or (v==7 and ((((x1+1)|y1)&1)==0)) or (v==8 and ((((x1+1)|(y1+1))&1)==0)) or (v==6 and (((x1|(y1+1))&1)==0)):
s[x1][y1] = s[x1][y1] + 1
if s[x1][y1] > 3:
s[x1][y1] = s[x1][y1] - 4
if dir1 == 1: if dir1 == 1:
x1 += signx x1 += signx
offsy += dy offsy += dy
@ -37,22 +78,37 @@ def line(y1, x1, y2, x2, v):
offsx -= dy offsx -= dy
# R, G, B, Alpha (0xFF = opaque): # R, G, B, Alpha (0xFF = opaque):
palette=[(0x00,0x00,0xaf,0xa0), (0x7f,0x0f,0xaf,0xb8)] palette=[
(0x30,0x03,0xaf,0xa4),
(0x4f,0x1c,0xaf,0xb4),
(0x7f,0x3d,0xa0,0xc8),
(0x6d,0x5d,0x99,0xb1)
]
for j in range(16): circles = h//w
i = j * 4 maxr = w//2
line(i, 0, 63-i, 63, 2) for i in [1,2,3,5,9,10,11,13]:
line(63, i, 0, 63-i, 2) for c in range(circles):
i+=1 q = ((circles-c-1)+i)%w
line(i, 64, 63-i, 127, 2) circle(maxr, maxr+c*w, q, 3)
line(63, 64+i, 0, 127-i, 2)
i+=1
line(i, 128, 63-i, 191, 2)
line(63, 128+i, 0, 191-i, 2)
i+=1
line(i, 192, 63-i, 255, 2)
line(63, 192+i, 0, 255-i, 2)
w = png.Writer(len(s[0]), len(s), palette=palette, bitdepth=1)
linesperside = 2
linestarts = round(w / linesperside) # 8
lineoffset = round(w / linestarts) # 2
wminus = w - 1
for j in range(linesperside):
for k in range(linestarts):
offset = k * w
for q in [0,1,3,4]:
# for q in [1]:
i = j*linestarts + ((k+q)%linestarts)
line(i, offset, wminus-i, offset+wminus, 5+(k&3))
line(wminus, offset+i, 0, offset+wminus-i, 5+(k&3))
w = png.Writer(len(s[0]), len(s), palette=palette, bitdepth=2)
f = open('mcl_portals_portal.png', 'wb') f = open('mcl_portals_portal.png', 'wb')
w.write(f, s) w.write(f, s)

View File

@ -0,0 +1,25 @@
import png
s = [
[
'1',
],
[
'11',
],
[
'111',
'111',
],
]
# R, G, B, Alpha (0xFF = opaque):
palette=[(0x00,0x00,0x00,0x00), (0x8F,0x69,0x66,0x9F)]
#palette=[(0x00,0x00,0x00,0x00), (0xF0,0xF0,0xF0,0x80)]
for i in range(0, len(s)):
print(str(i)+"/"+str(len(s)))
q = [[int(c) for c in row] for row in s[i]]
w = png.Writer(len(q[0]), len(q), palette=palette, bitdepth=1)
f = open('mcl_particles_nether_dust'+str(i+1)+'.png', 'wb')
w.write(f, q)