Merge branch 'master' of https://git.minetest.land/Wuzzy/MineClone2
|
@ -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
|
||||
* MysticTempest: Bugfixes
|
||||
* [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)
|
||||
|
||||
#### Mod credits (summary)
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -414,14 +414,17 @@ local function register_entity(entity_id, mesh, textures, drop, on_rightclick, o
|
|||
|
||||
-- Slow down or speed up
|
||||
local acc = dir.y * -1.8
|
||||
|
||||
local friction = 0.4
|
||||
local speed_mod = minetest.registered_nodes[minetest.get_node(pos).name]._rail_acceleration
|
||||
|
||||
acc = acc - friction
|
||||
|
||||
if has_fuel then
|
||||
acc = acc + 0.2
|
||||
elseif speed_mod and speed_mod ~= 0 then
|
||||
acc = acc + speed_mod
|
||||
else
|
||||
acc = acc - 0.4
|
||||
acc = acc + 0.6
|
||||
end
|
||||
|
||||
if speed_mod and speed_mod ~= 0 then
|
||||
acc = acc + speed_mod + friction
|
||||
end
|
||||
|
||||
new_acc = vector.multiply(dir, acc)
|
||||
|
|
|
@ -39,12 +39,6 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
dogshoot_count2_max = 5,
|
||||
passive = false,
|
||||
attack_animals = true,
|
||||
drops = {
|
||||
{name = mobs_mc.items.dragon_egg,
|
||||
chance = 1,
|
||||
min = 1,
|
||||
max = 1},
|
||||
},
|
||||
lava_damage = 0,
|
||||
fire_damage = 0,
|
||||
on_rightclick = nil,
|
||||
|
@ -58,8 +52,17 @@ mobs:register_mob("mobs_mc:enderdragon", {
|
|||
walk_start = 0, walk_end = 20,
|
||||
run_start = 0, run_end = 20,
|
||||
},
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ end
|
|||
dofile(modpath.."/weather_core.lua")
|
||||
dofile(modpath.."/snow.lua")
|
||||
dofile(modpath.."/rain.lua")
|
||||
dofile(modpath.."/nether_dust.lua")
|
||||
|
||||
if minetest.get_modpath("lightning") ~= nil then
|
||||
dofile(modpath.."/thunder.lua")
|
||||
|
|
39
mods/ENVIRONMENT/mcl_weather/nether_dust.lua
Normal 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)
|
After Width: | Height: | Size: 99 B |
After Width: | Height: | Size: 99 B |
After Width: | Height: | Size: 101 B |
|
@ -2,6 +2,8 @@ local S = minetest.get_translator("mcl_experience")
|
|||
mcl_experience = {}
|
||||
local pool = {}
|
||||
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 size_min, size_max = 20, 59 -- percents
|
||||
|
@ -45,7 +47,7 @@ end
|
|||
|
||||
-- saves data to be utilized on next login
|
||||
local save_data = function(player)
|
||||
name = player:get_player_name()
|
||||
local name = player:get_player_name()
|
||||
local temp_pool = pool[name]
|
||||
local meta = player:get_meta()
|
||||
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,
|
||||
position = def.position,
|
||||
text = def.text,
|
||||
text2 = def.text2,
|
||||
number = def.number,
|
||||
item = def.item,
|
||||
direction = def.direction,
|
||||
size = def.size,
|
||||
offset = def.offset,
|
||||
z_index = def.z_index,
|
||||
})
|
||||
-- create new 3d array here
|
||||
-- depends.txt is not needed
|
||||
|
@ -143,9 +148,8 @@ function mcl_experience.set_player_xp_level(player,level)
|
|||
return
|
||||
end
|
||||
pool[name].level = level
|
||||
pool[name].xp, 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_bg", element = "text", data = tostring(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", element = "text", data = tostring(level)})
|
||||
-- we may don't update the bar
|
||||
end
|
||||
|
||||
|
@ -158,40 +162,25 @@ minetest.register_on_joinplayer(function(player)
|
|||
name = player:get_player_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_elem_type = "statbar", position = {x=0.5, y=1},
|
||||
name = "experience bar", text = "experience_bar.png",
|
||||
number = temp_pool.bar, direction = 0,
|
||||
name = "experience bar",
|
||||
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)},
|
||||
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},
|
||||
name = "xp_level_bg", 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),
|
||||
name = "xp_level", text = tostring(temp_pool.level),
|
||||
number = 0xFFFFFF,
|
||||
offset = {x = -1, y = -(48 + 24 + 25)},
|
||||
z_index = 6,
|
||||
offset = {x = 0, y = -(48 + 24 + 24)},
|
||||
z_index = 12,
|
||||
})
|
||||
end)
|
||||
|
||||
|
@ -248,29 +237,32 @@ function mcl_experience.add_experience(player, experience)
|
|||
local temp_pool = pool[name]
|
||||
|
||||
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)
|
||||
if (temp_pool.xp >= temp_pool.xp_next_level) or (experience < 1) then
|
||||
temp_pool.xp = math.min(math.max(temp_pool.xp + experience, 0), max_xp)
|
||||
|
||||
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.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
|
||||
|
||||
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)})
|
||||
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
|
||||
|
||||
--reset player level
|
||||
|
@ -290,8 +282,7 @@ minetest.register_on_dieplayer(function(player)
|
|||
temp_pool.level = 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_bg", 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 = "experience_bar", element = "number", data = math.floor(temp_pool.bar)})
|
||||
|
||||
mcl_experience.throw_experience(player:get_pos(), xp_amount)
|
||||
|
@ -352,7 +343,7 @@ local function xp_step(self, dtime)
|
|||
|
||||
|
||||
self.age = self.age + dtime
|
||||
if self.age > 300 then
|
||||
if self.age > max_orb_age then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
@ -491,8 +482,8 @@ minetest.register_entity("mcl_experience:orb", {
|
|||
})
|
||||
|
||||
minetest.register_chatcommand("xp", {
|
||||
params = S("[<player>] [<xp>]"),
|
||||
description = S("Gives [[player <player>] <xp>] XP"),
|
||||
params = S("[[<player>] <xp>]"),
|
||||
description = S("Gives a player some XP"),
|
||||
privs = {server=true},
|
||||
func = function(name, params)
|
||||
local player, xp = nil, 1000
|
||||
|
@ -521,7 +512,6 @@ minetest.register_chatcommand("xp", {
|
|||
end
|
||||
mcl_experience.add_experience(player, xp)
|
||||
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)))
|
||||
end,
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[<player>] [<xp>]=[<игрок>] [<xp>]
|
||||
Gives [[player <player>] <xp>] XP=Даёт [[игроку <игрок> [<xp>]] единиц опыта XP
|
||||
[[<player>] <xp>]=[[<игрок>] <xp>]
|
||||
Gives a player some XP=Даёт игроку XP
|
||||
Error: Too many parameters!=Ошибка: слишком много параметров!
|
||||
Error: Incorrect value of XP=Ошибка: Недопустимое значение XP
|
||||
Error: Player not found=Ошибка: Игрок не найден
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[<player>] [<xp>]=
|
||||
Gives [[player <player>] <xp>] XP=
|
||||
[[<player>] <xp>]=
|
||||
Gives a player some XP=
|
||||
Error: Too many parameters!=
|
||||
Error: Incorrect value of XP=
|
||||
Error: Player not found=
|
||||
|
|
|
@ -197,7 +197,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
|
|||
if obj ~= self._shooter and obj:is_player() then
|
||||
ok = true
|
||||
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
|
||||
end
|
||||
end
|
||||
|
@ -219,7 +219,7 @@ ARROW_ENTITY.on_step = function(self, dtime)
|
|||
local obj = closest_object
|
||||
local is_player = obj:is_player()
|
||||
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
|
||||
-- Check if there is no solid node between arrow and object
|
||||
local ray = minetest.raycast(self.object:get_pos(), obj:get_pos(), true)
|
||||
|
|
Before Width: | Height: | Size: 188 B After Width: | Height: | Size: 324 B |
114
mods/ITEMS/mcl_end/end_crystal.lua
Normal 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")
|
|
@ -4,3 +4,6 @@ local basepath = minetest.get_modpath(minetest.get_current_modname())
|
|||
dofile(basepath.."/chorus_plant.lua")
|
||||
dofile(basepath.."/building.lua")
|
||||
dofile(basepath.."/eye_of_ender.lua")
|
||||
if not minetest.get_modpath("mcl_end_crystal") then
|
||||
dofile(basepath.."/end_crystal.lua")
|
||||
end
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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.
|
||||
|
|
|
@ -26,3 +26,8 @@ The stem attaches itself to end stone and other chorus blocks.=
|
|||
Grows on end stone=
|
||||
Randomly teleports you when eaten=
|
||||
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.=
|
||||
|
|
BIN
mods/ITEMS/mcl_end/models/mcl_end_crystal.b3d
Normal file
BIN
mods/ITEMS/mcl_end/models/mcl_end_crystal.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
mods/ITEMS/mcl_end/textures/mcl_end_crystal_item.png
Normal file
After Width: | Height: | Size: 356 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 561 B |
|
@ -157,7 +157,7 @@ local check_object_hit = function(self, pos, dmg)
|
|||
-- TODO: Deal knockback
|
||||
self.object:remove()
|
||||
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
|
||||
object:punch(self.object, 1.0, {
|
||||
full_punch_interval = 1.0,
|
||||
|
@ -196,22 +196,24 @@ end
|
|||
local snowball_on_step = function(self, dtime)
|
||||
self.timer=self.timer+dtime
|
||||
local pos = self.object:get_pos()
|
||||
local vel = self.object:get_velocity()
|
||||
local node = minetest.get_node(pos)
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
|
||||
|
||||
-- Destroy when hitting a solid node
|
||||
if self._lastpos.x~=nil 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)
|
||||
snowball_particles(self._lastpos, self.object:get_velocity())
|
||||
minetest.sound_play("mcl_throwing_snowball_impact_hard", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
|
||||
snowball_particles(self._lastpos, vel)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
snowball_particles(pos, self.object:get_velocity())
|
||||
minetest.sound_play("mcl_throwing_snowball_impact_soft", { pos = pos, max_hear_distance=16, gain=0.7 }, true)
|
||||
snowball_particles(pos, vel)
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
|
|
@ -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"},
|
||||
},
|
||||
})
|
|
@ -592,4 +592,3 @@ minetest.register_tool("mcl_tools:shears", {
|
|||
|
||||
dofile(minetest.get_modpath("mcl_tools").."/crafting.lua")
|
||||
dofile(minetest.get_modpath("mcl_tools").."/aliases.lua")
|
||||
dofile(minetest.get_modpath("mcl_tools").."/enchanting.lua")
|
||||
|
|
|
@ -30,5 +30,3 @@ Iron Sword=Eisenschwert
|
|||
Golden Sword=Goldschwert
|
||||
Diamond Sword=Diamantschwert
|
||||
Shears=Schere
|
||||
Enchanted @1=
|
||||
Enchanting Table=
|
||||
|
|
|
@ -30,5 +30,3 @@ Iron Sword=Espada de hierro
|
|||
Golden Sword=Espada de oro
|
||||
Diamond Sword=Espada de diamante
|
||||
Shears=Tijeras
|
||||
Enchanted @1=
|
||||
Enchanting Table=
|
||||
|
|
|
@ -30,5 +30,3 @@ Iron Sword=Épée en Fer
|
|||
Golden Sword=Épée en Or
|
||||
Diamond Sword=Épée en Diamant
|
||||
Shears=Cisailles
|
||||
Enchanted @1=
|
||||
Enchanting Table=
|
||||
|
|
|
@ -30,5 +30,3 @@ Iron Sword=Железный меч
|
|||
Golden Sword=Золотой меч
|
||||
Diamond Sword=Алмазный меч
|
||||
Shears=Ножницы
|
||||
Enchanted @1=@1 зачарованный(ая)
|
||||
Enchanting Table=Волшебный стол
|
||||
|
|
|
@ -30,5 +30,3 @@ Iron Sword=
|
|||
Golden Sword=
|
||||
Diamond Sword=
|
||||
Shears=
|
||||
Enchanted @1=
|
||||
Enchanting Table=
|
||||
|
|
|
@ -1,7 +1,44 @@
|
|||
import png
|
||||
w, h = 64, 256;
|
||||
w, h = 16, 128;
|
||||
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):
|
||||
signx = 1
|
||||
signy = 1
|
||||
|
@ -19,10 +56,14 @@ def line(y1, x1, y2, x2, v):
|
|||
if dx >= dy:
|
||||
dir1 = 1
|
||||
for i in range(max(dx, dy)+1):
|
||||
if v==2:
|
||||
s[x1][y1]=1-s[x1][y1]
|
||||
else:
|
||||
s[x1][y1] = v
|
||||
if(v == 1):
|
||||
s[x1][y1] = 1
|
||||
elif v==2:
|
||||
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:
|
||||
x1 += signx
|
||||
offsy += dy
|
||||
|
@ -37,22 +78,37 @@ def line(y1, x1, y2, x2, v):
|
|||
offsx -= dy
|
||||
|
||||
# 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):
|
||||
i = j * 4
|
||||
line(i, 0, 63-i, 63, 2)
|
||||
line(63, i, 0, 63-i, 2)
|
||||
i+=1
|
||||
line(i, 64, 63-i, 127, 2)
|
||||
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)
|
||||
circles = h//w
|
||||
maxr = w//2
|
||||
for i in [1,2,3,5,9,10,11,13]:
|
||||
for c in range(circles):
|
||||
q = ((circles-c-1)+i)%w
|
||||
circle(maxr, maxr+c*w, q, 3)
|
||||
|
||||
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')
|
||||
w.write(f, s)
|
||||
|
|
25
tools/create_texture__nether_dust.py
Normal 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)
|