update 1.0.1
|
@ -1,5 +1,5 @@
|
|||
-------------------------------------------------------------------------------------------------------------
|
||||
#Voxel Dungeon
|
||||
Voxel Dungeon
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
This is a recreation and adaptation of an Android rogue-like game, Pixel Dungeon by Watabou, using Minetest's engine. In particular, it is about exploring and digging into the five layers of the underground, in which access to the next layer is granted only upon summoning and defeating the boss of the current layer. Each of the sections is characterized by distinct terrain, monsters, and new ores. The boss of the final layer will grant the Amulet of Yendor; the player who picks this up will win the game.
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
Alpha 1.0.1:
|
||||
Blobs:
|
||||
No longer are anchored to entities
|
||||
All of any one type are tied to the same instance; multiple blobs no longer repeatedly apply their effect when stacked inside of each other
|
||||
A single blob also only applies its effect once per time frame
|
||||
The applying of blob effects has been greatly streamlined and causes much less lag than before
|
||||
New blobs no longer teleport some of themselves to any locations where previous blobs existed.
|
||||
TL;DR: They actually work now.
|
||||
|
||||
Fixed:
|
||||
Throwable items not being taken from the inventory in survival when thrown
|
||||
Random level algorithm of weapons and armor causing +3 and +2 equipment to become much more common than intended.
|
||||
Particles sometimes appearing far farther away from where they're intended to spawn
|
||||
|
||||
Visual:
|
||||
Added some textures of grass, dirt, and cobblestone originating from Sprouted Pixel Dungeon
|
|
@ -86,13 +86,19 @@ end
|
|||
|
||||
|
||||
|
||||
function entitycontrol.isAlive(index)
|
||||
local ent = entitycontrol.get_entity(index)
|
||||
|
||||
if ent and ent:get_pos() then return true end
|
||||
end
|
||||
|
||||
function entitycontrol.getFirstEmptyIndex(index)
|
||||
index = index or 1
|
||||
local ent = entitycontrol.get_entity(index)
|
||||
|
||||
if index > entitycontrol.count_entities() then
|
||||
return nil
|
||||
elseif ent and ent:get_pos() then
|
||||
elseif entitycontrol.isAlive(index) then
|
||||
return entitycontrol.getFirstEmptyIndex(index + 1)
|
||||
else
|
||||
return index
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
-------------------------------------------------------------------------------------------------------------
|
||||
#Voxel Dungeon
|
||||
Voxel Dungeon
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
This is a recreation and adaptation of an Android rogue-like game, Pixel Dungeon by Watabou, using Minetest's engine. In particular, it is about exploring and digging into the five layers of the underground, in which access to the next layer is granted only upon summoning and defeating the boss of the current layer. Each of the sections is characterized by distinct terrain, monsters, and new ores. The boss of the final layer will grant the Amulet of Yendor; the player who picks this up will win the game.
|
||||
|
|
|
@ -20,10 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||
--]]
|
||||
|
||||
voxeldungeon.blobs = {}
|
||||
--voxeldungeon.blobs.blob_instances = {}
|
||||
voxeldungeon.blobs.registered_blobs = {}
|
||||
|
||||
local TIMESCALE = 2
|
||||
local TIMESCALE = 1
|
||||
|
||||
local function expandUpon(posses, spreadcondition)
|
||||
local newposses = voxeldungeon.smartVectorTable()
|
||||
|
@ -32,13 +31,15 @@ local function expandUpon(posses, spreadcondition)
|
|||
local p = posses.getVector(i)
|
||||
local a = posses.getValue(i)
|
||||
|
||||
for _, n in pairs(voxeldungeon.utils.NEIGHBORS7) do
|
||||
local newpos = vector.add(p, n)
|
||||
if spreadcondition(newpos) then
|
||||
if not posses.get(newpos) and not newposses.get(newpos) then
|
||||
newposses.set(newpos, 0)
|
||||
elseif posses.get(newpos) then
|
||||
newposses.set(newpos, posses.get(newpos))
|
||||
if a > 0 then
|
||||
for _, n in pairs(voxeldungeon.utils.NEIGHBORS7) do
|
||||
local newpos = vector.add(p, n)
|
||||
if spreadcondition(newpos) then
|
||||
if not posses.get(newpos) and not newposses.get(newpos) then
|
||||
newposses.set(newpos, 0)
|
||||
elseif posses.get(newpos) then
|
||||
newposses.set(newpos, posses.get(newpos))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -47,115 +48,148 @@ local function expandUpon(posses, spreadcondition)
|
|||
return newposses
|
||||
end
|
||||
|
||||
function voxeldungeon.blobs.register(nme, spreadcondition, effect)
|
||||
local name = "voxeldungeon:blob_"..nme
|
||||
function voxeldungeon.blobs.register(name, spreadcondition, effect)
|
||||
name = "voxeldungeon:blob_"..name
|
||||
|
||||
minetest.register_entity(name,
|
||||
{
|
||||
physical = false,
|
||||
--textures = {"voxeldungeon_blank.png"},
|
||||
collisionbox = {0, 0, 0, 0, 0, 0},
|
||||
voxeldungeon.blobs.registered_blobs[name] = {}
|
||||
local blob = voxeldungeon.blobs.registered_blobs[name]
|
||||
|
||||
blob.posses = voxeldungeon.smartVectorTable()
|
||||
blob.offload = voxeldungeon.smartVectorTable()
|
||||
blob.volume = 0
|
||||
blob.timer = TIMESCALE
|
||||
|
||||
posses = voxeldungeon.smartVectorTable(),
|
||||
offload = voxeldungeon.smartVectorTable(),
|
||||
volume = 1000,
|
||||
offvolume = 1000,
|
||||
timer = TIMESCALE,
|
||||
blob.on_step = function(dtime)
|
||||
if blob.timer > 0 then
|
||||
blob.timer = blob.timer - dtime
|
||||
return
|
||||
end
|
||||
|
||||
on_activate = function(self)
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
if self.timer > 0 then
|
||||
self.timer = self.timer - dtime
|
||||
return
|
||||
end
|
||||
|
||||
self.timer = TIMESCALE
|
||||
blob.timer = TIMESCALE
|
||||
|
||||
if self.volume > 0 then
|
||||
self.volume = 0
|
||||
if blob.volume > 0 then
|
||||
blob.volume = 0
|
||||
|
||||
self._evolve(self)
|
||||
blob.evolve()
|
||||
|
||||
local temp = self.offload
|
||||
self.offload = self.posses
|
||||
self.posses = temp
|
||||
local temp = blob.offload
|
||||
blob.offload = blob.posses
|
||||
blob.posses = temp
|
||||
|
||||
self.offvolume = self.volume
|
||||
else
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
end,
|
||||
for i = 1, blob.posses.size() do
|
||||
local p = blob.posses.getVector(i)
|
||||
local v = blob.posses.getValue(i)
|
||||
|
||||
_evolve = function(self)
|
||||
if not self.posses.get(self.object:get_pos()) then return end
|
||||
local objs = {}
|
||||
|
||||
if self.offvolume / self.posses.size() >= 5 then
|
||||
self.posses = expandUpon(self.posses, spreadcondition)
|
||||
end
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local pos = vector.round(player:get_pos())
|
||||
|
||||
for i = 1, self.posses.size() do
|
||||
local p = self.posses.getVector(i)
|
||||
local a = self.posses.getValue(i)
|
||||
if vector.equals(pos, p) then
|
||||
table.insert(objs, player)
|
||||
end
|
||||
end
|
||||
|
||||
if spreadcondition(p) then
|
||||
local count = 1
|
||||
local sum = a or 0
|
||||
for e = 1, entitycontrol.count_entities() do
|
||||
local entity = entitycontrol.get_entity(e)
|
||||
|
||||
for _, n in pairs(voxeldungeon.utils.NEIGHBORS6) do
|
||||
local neighbor = vector.add(p, n)
|
||||
if not voxeldungeon.utils.solid(neighbor) then
|
||||
sum = sum + (self.posses.get(neighbor) or 0)
|
||||
count = count + 1
|
||||
if entitycontrol.isAlive(e) then
|
||||
local pos = vector.round(entity:get_pos())
|
||||
|
||||
if vector.equals(pos, p) then
|
||||
table.insert(objs, entity)
|
||||
end
|
||||
end
|
||||
|
||||
local value = 0
|
||||
if sum >= count then
|
||||
value = math.floor(sum / count) - 1
|
||||
end
|
||||
|
||||
self.offload.set(p, value)
|
||||
self.volume = self.volume + value
|
||||
effect(p, value)
|
||||
else
|
||||
self.offload.del(p)
|
||||
end
|
||||
|
||||
effect(blob, p, v, objs)
|
||||
end
|
||||
end,
|
||||
end
|
||||
end
|
||||
|
||||
_seed = function(self, amount)
|
||||
self.volume = amount
|
||||
self.offvolume = self.volume
|
||||
self.posses.set(self.object:get_pos(), self.volume)
|
||||
end,
|
||||
})
|
||||
|
||||
voxeldungeon.blobs.registered_blobs[name] = minetest.registered_entities[name]
|
||||
blob.evolve = function()
|
||||
blob.offload = expandUpon(blob.posses, spreadcondition)
|
||||
|
||||
for i = 1, blob.offload.size() do
|
||||
local p = blob.offload.getVector(i)
|
||||
|
||||
if spreadcondition(p) then
|
||||
local count = 1
|
||||
local sum = blob.posses.getValue(i) or 0
|
||||
|
||||
for _, n in pairs(voxeldungeon.utils.NEIGHBORS6) do
|
||||
local neighbor = vector.add(p, n)
|
||||
if not voxeldungeon.utils.solid(neighbor) then
|
||||
sum = sum + (blob.posses.get(neighbor) or 0)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
local value = 0
|
||||
if sum >= count then
|
||||
value = math.floor(sum / count) - 1
|
||||
end
|
||||
|
||||
blob.offload.set(p, value)
|
||||
blob.volume = blob.volume + value
|
||||
else
|
||||
blob.offload.del(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
blob.seed = function(pos, amount)
|
||||
blob.volume = blob.volume + amount
|
||||
blob.posses.set(pos, amount)
|
||||
end
|
||||
|
||||
minetest.register_globalstep(blob.on_step)
|
||||
end
|
||||
|
||||
function voxeldungeon.blobs.seed(nme, pos, amount)
|
||||
local name = "voxeldungeon:blob_"..nme
|
||||
function voxeldungeon.blobs.seed(name, pos, amount)
|
||||
name = "voxeldungeon:blob_"..name
|
||||
pos = vector.round(pos)
|
||||
local obj = minetest.add_entity(pos, name)
|
||||
|
||||
if obj then
|
||||
local blob = obj:get_luaentity()
|
||||
blob._seed(blob, amount)
|
||||
end
|
||||
voxeldungeon.blobs.registered_blobs[name].seed(pos, amount)
|
||||
end
|
||||
|
||||
voxeldungeon.blobs.register("toxicgas", function(pos)
|
||||
return not voxeldungeon.utils.solid(pos)
|
||||
end, function(pos, amount)
|
||||
local objs = minetest.get_objects_inside_radius(pos, 1)
|
||||
for _, obj in pairs(objs) do
|
||||
obj:set_hp(obj:get_hp() - 1)
|
||||
|
||||
|
||||
voxeldungeon.blobs.register("fire",
|
||||
function(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
return true--node and minetest.get_item_group(node.name, "flammable") >= 1
|
||||
end,
|
||||
|
||||
function(blob, pos, amount, objs)
|
||||
for _, obj in ipairs(objs) do
|
||||
if obj:is_player() then
|
||||
obj:set_hp(obj:get_hp() - 2)
|
||||
else
|
||||
voxeldungeon.mobs.damage(obj, 2, "fire")
|
||||
end
|
||||
end
|
||||
|
||||
voxeldungeon.particles.factory("flame", pos, 1, TIMESCALE)
|
||||
end
|
||||
|
||||
if math.random(5) == 1 then
|
||||
voxeldungeon.particles.burst("toxic", pos, 1)
|
||||
)
|
||||
|
||||
voxeldungeon.blobs.register("toxicgas",
|
||||
function(pos)
|
||||
return not voxeldungeon.utils.solid(pos)
|
||||
end,
|
||||
|
||||
function(blob, pos, amount, objs)
|
||||
for _, obj in ipairs(objs) do
|
||||
if obj:is_player() then
|
||||
obj:set_hp(obj:get_hp() - voxeldungeon.utils.getChapter(pos))
|
||||
else
|
||||
voxeldungeon.mobs.damage(obj, voxeldungeon.utils.getChapter(pos), "toxic gas")
|
||||
end
|
||||
end
|
||||
|
||||
if voxeldungeon.utils.randomDecimal(blob.posses.size() / (blob.posses.size() + 2)) <= 1/3 then
|
||||
voxeldungeon.particles.burst("toxic", pos, 1)
|
||||
end
|
||||
end
|
||||
end)
|
||||
)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
Alpha 1.0.1:
|
||||
Blobs:
|
||||
No longer are anchored to entities
|
||||
All of any one type are tied to the same instance; multiple blobs no longer repeatedly apply their effect when stacked inside of each other
|
||||
A single blob also only applies its effect once per time frame
|
||||
The applying of blob effects has been greatly streamlined and causes much less lag than before
|
||||
New blobs no longer teleport some of themselves to any locations where previous blobs existed.
|
||||
TL;DR: They actually work now.
|
||||
|
||||
Fixed:
|
||||
Throwable items not being taken from the inventory in survival when thrown
|
||||
Random level algorithm of weapons and armor causing +3 and +2 equipment to become much more common than intended.
|
||||
Particles sometimes appearing far farther away from where they're intended to spawn
|
||||
Punching often dealing no damage to rats.
|
||||
|
||||
Visual:
|
||||
Added some textures of grass, dirt, and cobblestone originating from Sprouted Pixel Dungeon
|
||||
Toxic particles now spin
|
|
@ -1,47 +0,0 @@
|
|||
--[[
|
||||
Voxel Dungeon
|
||||
Copyright (C) 2019 Noodlemire
|
||||
|
||||
Pixel Dungeon
|
||||
Copyright (C) 2012-2015 Oleg Dolya
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
--]]
|
||||
|
||||
--A set of methods commonly caused by a variety of mechanics
|
||||
|
||||
function voxeldungeon.randomteleport(obj)
|
||||
for try = 1, 10 do
|
||||
local p = obj:get_pos()
|
||||
|
||||
local testpos =
|
||||
{
|
||||
x = p.x + math.random(-100, 100),
|
||||
y = p.y + 0.5,
|
||||
z = p.z + math.random(-100, 100)
|
||||
}
|
||||
|
||||
if not minetest.registered_nodes[minetest.get_node(testpos).name].walkable then
|
||||
obj:set_pos(testpos)
|
||||
|
||||
minetest.sound_play("voxeldungeon_teleport",
|
||||
{
|
||||
pos = obj:get_pos(),
|
||||
gain = 1.0,
|
||||
max_hear_distance = 32,
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
|
@ -259,19 +259,24 @@ local weaponChances = {
|
|||
},
|
||||
}
|
||||
|
||||
function voxeldungeon.generator.randomArmor(t)
|
||||
local tier = t or 1
|
||||
local arm = voxeldungeon.utils.randomChances(armorChances[tier])
|
||||
local function randomLevel()
|
||||
local level = 0
|
||||
|
||||
for i = 3, 1, -1 do
|
||||
if math.random(3 * i) == 1 then
|
||||
if math.random(math.pow(3, i)) == 1 then
|
||||
level = i
|
||||
end
|
||||
end
|
||||
|
||||
return level
|
||||
end
|
||||
|
||||
function voxeldungeon.generator.randomArmor(t)
|
||||
local tier = t or 1
|
||||
local arm = voxeldungeon.utils.randomChances(armorChances[tier])
|
||||
|
||||
local itemstack = ItemStack({name = arm, count = 1, wear = 0, metadata = ""})
|
||||
voxeldungeon.tools.setLevelOf(itemstack, level)
|
||||
voxeldungeon.tools.setLevelOf(itemstack, randomLevel())
|
||||
return itemstack
|
||||
end
|
||||
|
||||
|
@ -308,16 +313,9 @@ end
|
|||
function voxeldungeon.generator.randomWeapon(t)
|
||||
local tier = t or 1
|
||||
local wep = voxeldungeon.utils.randomChances(weaponChances[tier])
|
||||
local level = 0
|
||||
|
||||
for i = 3, 1, -1 do
|
||||
if math.random(3 * i) == 1 then
|
||||
level = i
|
||||
end
|
||||
end
|
||||
|
||||
local itemstack = ItemStack({name = wep, count = 1, wear = 0, metadata = ""})
|
||||
voxeldungeon.tools.setLevelOf(itemstack, level)
|
||||
voxeldungeon.tools.setLevelOf(itemstack, randomLevel())
|
||||
return itemstack
|
||||
end
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ voxeldungeon.wp = minetest.get_worldpath()..'/'
|
|||
--Load library files
|
||||
dofile(mp.."utils.lua")
|
||||
dofile(mp.."override.lua")
|
||||
dofile(mp.."commoneffects.lua")
|
||||
dofile(mp.."smartvectortable.lua")
|
||||
dofile(mp.."glog.lua")
|
||||
dofile(mp.."playerhandler.lua")
|
||||
|
|
|
@ -19,39 +19,64 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
--]]
|
||||
|
||||
minetest.register_craftitem("voxeldungeon:bomb", {
|
||||
description = voxeldungeon.utils.itemDescription("Bomb\n \nThis is a relatively small bomb, filled with black powder. Conveniently, its fuse is lit automatically when the bomb is thrown.\n \nRight-click while holding a bomb to throw it."),
|
||||
inventory_image = "voxeldungeon_item_bomb.png",
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
tnt.boom(pointed_thing.above, {radius = 2, damage_radius = 2})
|
||||
end,
|
||||
|
||||
on_secondary_use = function(itemstack, user, pointed_thing)
|
||||
local function get_pointed_pos(pointed_thing)
|
||||
if pointed_thing.type == "node" then
|
||||
return pointed_thing.above
|
||||
elseif pointed_thing.type == "object" then
|
||||
return pointed_thing.ref:get_pos()
|
||||
end
|
||||
end
|
||||
|
||||
function voxeldungeon.register_throwingitem(name, desc, callback, itemdef, entdef)
|
||||
itemdef = itemdef or {}
|
||||
entdef = entdef or {}
|
||||
|
||||
itemdef.description = voxeldungeon.utils.itemDescription(desc)
|
||||
itemdef.inventory_image = itemdef.inventory_image or "voxeldungeon_item_"..name..".png"
|
||||
|
||||
itemdef.on_place = function(itemstack, placer, pointed_thing)
|
||||
callback(get_pointed_pos(pointed_thing))
|
||||
|
||||
return voxeldungeon.utils.take_item(placer, itemstack)
|
||||
end
|
||||
|
||||
itemdef.on_secondary_use = function(itemstack, user, pointed_thing)
|
||||
local pos = vector.add(user:get_pos(), {x=0, y=1, z=0})
|
||||
local offset = vector.multiply(user:get_look_dir(), 2)
|
||||
|
||||
local projectile = minetest.add_entity(vector.add(pos, offset), "voxeldungeon:thrown_bomb")
|
||||
local projectile = minetest.add_entity(vector.add(pos, offset), "voxeldungeon:thrown_"..name)
|
||||
projectile:set_velocity(vector.multiply(offset, 8))
|
||||
projectile:set_acceleration({x = 0, y = -12, z = 0})
|
||||
|
||||
return voxeldungeon.utils.take_item(user, itemstack)
|
||||
end
|
||||
})
|
||||
minetest.register_entity("voxeldungeon:thrown_bomb", {
|
||||
initial_properties = {
|
||||
|
||||
entdef.initial_properties = {
|
||||
visual = "sprite",
|
||||
pointable = false,
|
||||
textures = {"voxeldungeon_item_bomb.png"},
|
||||
},
|
||||
textures = {(itemdef.inventory_image or "voxeldungeon_item_"..name..".png")},
|
||||
}
|
||||
|
||||
on_step = function(self, dtime)
|
||||
entdef.on_step = function(self, dtime)
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
if voxeldungeon.utils.solid(vector.add(pos, vector.normalize(self.object:get_velocity()))) then
|
||||
tnt.boom(pos, {radius = 2, damage_radius = 2})
|
||||
callback(pos)
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craftitem("voxeldungeon:"..name, itemdef)
|
||||
minetest.register_entity("voxeldungeon:thrown_"..name, entdef)
|
||||
end
|
||||
|
||||
|
||||
|
||||
voxeldungeon.register_throwingitem("bomb", "Bomb\n \nThis is a relatively small bomb, filled with black powder. Conveniently, its fuse is lit automatically when the bomb is thrown.\n \nRight-click while holding a bomb to throw it.", function(pos)
|
||||
tnt.boom(pos, {radius = 2, damage_radius = 2})
|
||||
end)
|
||||
|
||||
minetest.register_craftitem("voxeldungeon:demonite_lump", {
|
||||
description = "Demonite Lump",
|
||||
|
@ -88,42 +113,9 @@ minetest.register_craftitem("voxeldungeon:gold", {
|
|||
stack_max = 99999,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("voxeldungeon:honeypot", {
|
||||
description = voxeldungeon.utils.itemDescription("Honeypot\n \nThis large honeypot is only really lined with honey, instead it houses a giant bee! These sorts of massive bees usually stay in their hives, perhaps the pot is some sort of specialized trapper's cage? The bee seems pretty content inside the pot with its honey, and buzzes at you warily when you look at it.\n \nRight-click while holding a honeypot to throw it."),
|
||||
inventory_image = "voxeldungeon_item_honeypot.png",
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
minetest.add_entity(pointed_thing.above, "voxeldungeon:bee")
|
||||
end,
|
||||
|
||||
on_secondary_use = function(itemstack, user, pointed_thing)
|
||||
local pos = vector.add(user:get_pos(), {x=0, y=1, z=0})
|
||||
local offset = vector.multiply(user:get_look_dir(), 2)
|
||||
|
||||
local projectile = minetest.add_entity(vector.add(pos, offset), "voxeldungeon:thrown_honeypot")
|
||||
projectile:set_velocity(vector.multiply(offset, 8))
|
||||
projectile:set_acceleration({x = 0, y = -12, z = 0})
|
||||
end
|
||||
})
|
||||
minetest.register_entity("voxeldungeon:thrown_honeypot", {
|
||||
initial_properties = {
|
||||
visual = "sprite",
|
||||
pointable = false,
|
||||
textures = {"voxeldungeon_item_honeypot.png"},
|
||||
},
|
||||
|
||||
on_step = function(self, dtime)
|
||||
local pos = self.object:get_pos()
|
||||
|
||||
if voxeldungeon.utils.solid(vector.add(pos, vector.normalize(self.object:get_velocity()))) then
|
||||
minetest.add_entity(pos, "voxeldungeon:bee")
|
||||
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
voxeldungeon.register_throwingitem("honeypot", "Honeypot\n \nThis large honeypot is only really lined with honey, instead it houses a giant bee! These sorts of massive bees usually stay in their hives, perhaps the pot is some sort of specialized trapper's cage? The bee seems pretty content inside the pot with its honey, and buzzes at you warily when you look at it.\n \nRight-click while holding a honeypot to throw it.", function(pos)
|
||||
minetest.add_entity(pos, "voxeldungeon:bee")
|
||||
end)
|
||||
|
||||
minetest.override_item("default:torch", {
|
||||
description = voxeldungeon.utils.itemDescription("Torch\n \nIt's an indispensable item in the underground, which is notorious for its poor ambient lighting."),
|
||||
|
|
|
@ -61,7 +61,7 @@ mobs:register_mob("voxeldungeon:rat", {
|
|||
damage = 3,
|
||||
hp_min = 8,
|
||||
hp_max = 8,
|
||||
armor = 99,
|
||||
armor = 100,
|
||||
collisionbox = {-0.4, -0.5, -0.4, 0.4, 0.5, 0.4},
|
||||
visual = "sprite",
|
||||
textures = {"voxeldungeon_icon_mob_rat.png"},
|
||||
|
|
|
@ -24,30 +24,40 @@ voxeldungeon.particles = {}
|
|||
local registered_particles = {}
|
||||
local registered_factories = {}
|
||||
|
||||
function voxeldungeon.particles.register_particle(name, radius, lifespan, gravity, transformation, drawtype, yscale)
|
||||
local function randomVel()
|
||||
return math.random(-1/3, 1/3)
|
||||
end
|
||||
|
||||
function voxeldungeon.particles.register_particle(name, radius, lifespan, gravity, initialize, transformation, drawtype, yscale, frames)
|
||||
local scale = radius * 0.125
|
||||
frames = frames or 1
|
||||
minetest.register_entity("voxeldungeon:particle_"..name,
|
||||
{
|
||||
physical = false,
|
||||
timer = 0,
|
||||
_timer = 0,
|
||||
|
||||
textures = {"voxeldungeon_particle_"..name..".png"},
|
||||
visual_size =
|
||||
{
|
||||
x = scale,
|
||||
y = scale * (yscale or 1)
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
textures = {"voxeldungeon_particle_"..name..".png"},
|
||||
visual_size =
|
||||
{
|
||||
x = scale,
|
||||
y = scale * (yscale or 1)
|
||||
},
|
||||
collisionbox = {0, 0, 0, 0, 0, 0},
|
||||
visual = drawtype or "sprite",
|
||||
spritediv = {x = 1, y = frames}
|
||||
},
|
||||
collisionbox = {0, 0, 0, 0, 0, 0},
|
||||
visual = drawtype or "sprite",
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
local obj = self.object
|
||||
|
||||
obj:setvelocity(
|
||||
{
|
||||
x=(math.random(0,60)-30)/45,
|
||||
y=(math.random(0,60)-30)/45,
|
||||
z=(math.random(0,60)-30)/45
|
||||
x = randomVel(),
|
||||
y = randomVel(),
|
||||
z = randomVel(),
|
||||
})
|
||||
|
||||
local v = obj:get_velocity()
|
||||
local ax = v.x
|
||||
if ax ~= 0 then ax = -ax / math.abs(ax) / lifespan / 2 end
|
||||
|
@ -58,13 +68,15 @@ function voxeldungeon.particles.register_particle(name, radius, lifespan, gravit
|
|||
|
||||
obj:setacceleration({x=ax, y=ay+gravity, z=az})
|
||||
obj:setyaw(math.random(0,359)/180*math.pi)
|
||||
|
||||
if initialize then initialize(self) end
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
transformation(self, lifespan)
|
||||
if transformation then transformation(self, lifespan) end
|
||||
|
||||
self.timer = self.timer+dtime
|
||||
if self.timer >= lifespan then
|
||||
self._timer = self._timer+dtime
|
||||
if self._timer >= lifespan then
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
|
@ -74,8 +86,8 @@ function voxeldungeon.particles.register_particle(name, radius, lifespan, gravit
|
|||
{
|
||||
visual_size =
|
||||
{
|
||||
x = scale + self.timer * change,
|
||||
y = scale * (yscale or 1) + self.timer * change
|
||||
x = scale + self._timer * change,
|
||||
y = scale * (yscale or 1) + self._timer * change
|
||||
}
|
||||
})
|
||||
end,
|
||||
|
@ -84,8 +96,24 @@ end
|
|||
|
||||
|
||||
|
||||
voxeldungeon.particles.register_particle("poison", 1, 0.6, -1, function(self, lifespan)
|
||||
local timer = self.timer
|
||||
voxeldungeon.particles.register_particle("flame", 8, 0.8, 1,
|
||||
function(self)
|
||||
local gbyte = math.random(155, 222)
|
||||
local ghex = voxeldungeon.utils.tohex(gbyte)
|
||||
self.object:settexturemod("^[colorize:#FF"..ghex.."00")
|
||||
end,
|
||||
|
||||
function(self, lifespan)
|
||||
self.resize(self, -0.125)
|
||||
end
|
||||
)
|
||||
|
||||
voxeldungeon.particles.register_particle("grass", 1, 1.2, 1, nil, function(self, lifespan)
|
||||
self.resize(self, -0.075)
|
||||
end)
|
||||
|
||||
voxeldungeon.particles.register_particle("poison", 1, 0.6, -1, nil, function(self, lifespan)
|
||||
local timer = self._timer
|
||||
|
||||
local sbyte = 150 + (lifespan - timer) / lifespan * 100
|
||||
local shex = voxeldungeon.utils.tohex(sbyte)
|
||||
|
@ -96,24 +124,26 @@ voxeldungeon.particles.register_particle("poison", 1, 0.6, -1, function(self, li
|
|||
self.resize(self, 0.125)
|
||||
end)
|
||||
|
||||
voxeldungeon.particles.register_particle("grass", 1, 1.2, 1, function(self, lifespan)
|
||||
self.resize(self, -0.075)
|
||||
end)
|
||||
voxeldungeon.particles.register_particle("shaft", 2, 1.2, 0, nil, nil, "upright_sprite", 8)
|
||||
|
||||
voxeldungeon.particles.register_particle("shaft", 2, 1.2, 0, function(self, lifespan) end, "upright_sprite", 8)
|
||||
voxeldungeon.particles.register_particle("toxic", 8, 3, 0,
|
||||
function(self)
|
||||
self.object:set_sprite({x = 0, y = 0}, 12, voxeldungeon.utils.randomDecimal(0.4, 0.3), false)
|
||||
end,
|
||||
|
||||
voxeldungeon.particles.register_particle("toxic", 8, 3, 0, function(self, lifespan)
|
||||
self.resize(self, 0.05)
|
||||
end)
|
||||
function(self, lifespan)
|
||||
self.resize(self, 0.25)
|
||||
end, "sprite", 1, 12
|
||||
)
|
||||
|
||||
|
||||
|
||||
function voxeldungeon.particles.burst(name, pos, amount)
|
||||
pos = vector.add(pos,
|
||||
{
|
||||
x = math.random(-0.5, 0.5),
|
||||
y = math.random(-0.5, 0.5),
|
||||
z = math.random(-0.5, 0.5),
|
||||
x = voxeldungeon.utils.randomDecimal(0.25, -0.25),
|
||||
y = voxeldungeon.utils.randomDecimal(0.25, -0.25),
|
||||
z = voxeldungeon.utils.randomDecimal(0.25, -0.25),
|
||||
})
|
||||
|
||||
for i = 1, amount do
|
||||
|
|
|
@ -161,7 +161,7 @@ end
|
|||
|
||||
voxeldungeon.register_plant("fadeleaf", "Fadeleaf\n \nTouching a Fadeleaf will teleport any creature to a random place within 100 blocks.", function(pos, objs)
|
||||
for i = 1, #objs do
|
||||
voxeldungeon.randomteleport(objs[i])
|
||||
voxeldungeon.utils.randomteleport(objs[i])
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ local potion_defs =
|
|||
voxeldungeon.playerhandler.changeSTR(user, 1)
|
||||
voxeldungeon.glog.p("Newfound strength surges through your body.", user)
|
||||
voxeldungeon.tools.updateStrdiffArmor(user)
|
||||
return voxeldungeon.utils.take_item(user, itemstack)
|
||||
end
|
||||
},
|
||||
{
|
||||
|
@ -43,6 +42,14 @@ local potion_defs =
|
|||
{
|
||||
name = "liquidflame",
|
||||
desc = "Liquid Flame",
|
||||
|
||||
shatter = function(pos)
|
||||
--[[for _, n in ipairs(voxeldungeon.utils.NEIGHBORS27) do
|
||||
local f = vector.add(pos, n)
|
||||
|
||||
voxeldungeon.blobs.seed("fire", f, 200)
|
||||
end--]]
|
||||
end
|
||||
},
|
||||
{
|
||||
name = "might",
|
||||
|
@ -154,36 +161,25 @@ local function default_shatter(pos, color)
|
|||
end
|
||||
|
||||
local function register_potion(name, desc, color, drink, shatter)
|
||||
minetest.register_entity("voxeldungeon:thrownpotion_"..color, {
|
||||
initial_properties = {
|
||||
visual = "sprite",
|
||||
pointable = false,
|
||||
textures = {"voxeldungeon_item_potion_"..color..".png"},
|
||||
},
|
||||
|
||||
on_step = function(self, dtime)
|
||||
if voxeldungeon.utils.solid(vector.add(self.object:get_pos(), vector.normalize(self.object:get_velocity()))) then
|
||||
if shatter then
|
||||
shatter(self.object:get_pos())
|
||||
else
|
||||
default_shatter(self.object:get_pos(), color)
|
||||
end
|
||||
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_craftitem("voxeldungeon:potion_"..name,
|
||||
{
|
||||
description = voxeldungeon.utils.itemDescription("Potion of "..desc..
|
||||
voxeldungeon.register_throwingitem("potion_"..name, "Potion of "..desc..
|
||||
"\n \nLeft click while holding a potion to drink it."..
|
||||
"\nRight click while holding a potion to throw it."),
|
||||
"\nRight click while holding a potion to throw it.",
|
||||
function(pos)
|
||||
if shatter then
|
||||
shatter(pos)
|
||||
else
|
||||
default_shatter(pos, color)
|
||||
end
|
||||
end,
|
||||
|
||||
{
|
||||
inventory_image = "voxeldungeon_item_potion_"..color..".png",
|
||||
_cornerLR = "voxeldungeon_icon_potion_"..name..".png",
|
||||
|
||||
on_use = drink or function(itemstack, user)
|
||||
if shatter then
|
||||
on_use = function(itemstack, user)
|
||||
if drink then
|
||||
drink(itemstack, user)
|
||||
elseif shatter then
|
||||
shatter(user:get_pos())
|
||||
else
|
||||
default_shatter(user:get_pos(), color)
|
||||
|
@ -191,25 +187,6 @@ local function register_potion(name, desc, color, drink, shatter)
|
|||
|
||||
return voxeldungeon.utils.take_item(user, itemstack)
|
||||
end,
|
||||
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if shatter then
|
||||
shatter(pointed_thing.above)
|
||||
else
|
||||
default_shatter(pointed_thing.above, color)
|
||||
end
|
||||
|
||||
return voxeldungeon.utils.take_item(placer, itemstack)
|
||||
end,
|
||||
|
||||
on_secondary_use = function(itemstack, user, pointed_thing)
|
||||
local pos = vector.add(user:get_pos(), {x=0, y=1, z=0})
|
||||
local offset = vector.multiply(user:get_look_dir(), 2)
|
||||
|
||||
local projectile = minetest.add_entity(vector.add(pos, offset), "voxeldungeon:thrownpotion_"..color)
|
||||
projectile:set_velocity(vector.multiply(offset, 8))
|
||||
projectile:set_acceleration({x = 0, y = -12, z = 0})
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ local scroll_defs =
|
|||
desc = "Teleportation\n \nThe spell on this parchment instantly transports the reader to a random location up to 100 blocks away. It can be used to escape a dangerous situation, but an unlucky reader might find himself in an even more dangerous place.",
|
||||
|
||||
read = function(itemstack, user, pointed_thing)
|
||||
voxeldungeon.randomteleport(user)
|
||||
voxeldungeon.utils.randomteleport(user)
|
||||
return voxeldungeon.utils.take_item(user, itemstack)
|
||||
end
|
||||
},
|
||||
|
|
|
@ -25,8 +25,6 @@ function voxeldungeon.smartVectorTable()
|
|||
svt.table = {}
|
||||
|
||||
svt.set = function(keyVect, value)
|
||||
if not keyVect or not value then return end
|
||||
|
||||
for _, v in ipairs(svt.table) do
|
||||
if vector.equals(keyVect, v.k) then
|
||||
v.v = value
|
||||
|
@ -37,6 +35,11 @@ function voxeldungeon.smartVectorTable()
|
|||
table.insert(svt.table, {k = keyVect, v = value})
|
||||
end
|
||||
|
||||
svt.add = function(keyVect, value)
|
||||
local old = svt.get(keyVect) or 0
|
||||
svt.set(keyVect, old + value)
|
||||
end
|
||||
|
||||
svt.del = function(keyVect)
|
||||
for i, v in ipairs(svt.table) do
|
||||
if vector.equals(keyVect, v.k) then
|
||||
|
@ -57,10 +60,12 @@ function voxeldungeon.smartVectorTable()
|
|||
end
|
||||
|
||||
svt.getVector = function(i)
|
||||
if not svt.table[i] then return end
|
||||
return svt.table[i].k
|
||||
end
|
||||
|
||||
svt.getValue = function(i)
|
||||
if not svt.table[i] then return end
|
||||
return svt.table[i].v
|
||||
end
|
||||
|
||||
|
@ -68,6 +73,17 @@ function voxeldungeon.smartVectorTable()
|
|||
return #svt.table
|
||||
end
|
||||
|
||||
svt.combineWith = function(other)
|
||||
for i = 1, other.size() do
|
||||
local k = other.getVector(i)
|
||||
local v = other.getValue(i)
|
||||
|
||||
local old = svt.get(k) or 0
|
||||
|
||||
svt.set(k, old + v)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
svt.iterator = function()
|
||||
local function SVTiterate(i)
|
||||
|
|
Before Width: | Height: | Size: 5.6 KiB |
|
@ -19,8 +19,27 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
--]]
|
||||
|
||||
|
||||
|
||||
voxeldungeon.tools = {}
|
||||
|
||||
|
||||
|
||||
if not minetest.settings:get_bool("creative_mode") then
|
||||
minetest.override_item("", {
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 0.667,
|
||||
max_drop_level = 0,
|
||||
groupcaps = {
|
||||
crumbly = {times={[2]=3.00, [3]=0.70}, uses=0, maxlevel=1},
|
||||
snappy = {times={[3]=0.40}, uses=0, maxlevel=1},
|
||||
oddly_breakable_by_hand = {times={[1]=3.50,[2]=2.00,[3]=0.70}, uses=0}
|
||||
},
|
||||
damage_groups = {fleshy = 1},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
minetest.override_item("default:pick_wood", {
|
||||
max_drop_level=1
|
||||
})
|
||||
|
|
|
@ -87,6 +87,37 @@ voxeldungeon.utils.NEIGHBORS26 =
|
|||
{x = 1, y = 1, z = 1},
|
||||
}
|
||||
|
||||
voxeldungeon.utils.NEIGHBORS27 =
|
||||
{
|
||||
{x = -1, y = -1, z = -1},
|
||||
{x = 0, y = -1, z = -1},
|
||||
{x = 1, y = -1, z = -1},
|
||||
{x = -1, y = 0, z = -1},
|
||||
{x = 0, y = 0, z = -1},
|
||||
{x = 1, y = 0, z = -1},
|
||||
{x = -1, y = 1, z = -1},
|
||||
{x = 0, y = 1, z = -1},
|
||||
{x = 1, y = 1, z = -1},
|
||||
{x = -1, y = -1, z = 0},
|
||||
{x = 0, y = -1, z = 0},
|
||||
{x = 1, y = -1, z = 0},
|
||||
{x = -1, y = 0, z = 0},
|
||||
{x = 0, y = 0, z = 0},
|
||||
{x = 1, y = 0, z = 0},
|
||||
{x = -1, y = 1, z = 0},
|
||||
{x = 0, y = 1, z = 0},
|
||||
{x = 1, y = 1, z = 0},
|
||||
{x = -1, y = -1, z = 1},
|
||||
{x = 0, y = -1, z = 1},
|
||||
{x = 1, y = -1, z = 1},
|
||||
{x = -1, y = 0, z = 1},
|
||||
{x = 0, y = 0, z = 1},
|
||||
{x = 1, y = 0, z = 1},
|
||||
{x = -1, y = 1, z = 1},
|
||||
{x = 0, y = 1, z = 1},
|
||||
{x = 1, y = 1, z = 1},
|
||||
}
|
||||
|
||||
|
||||
|
||||
voxeldungeon.utils.surface_valid_ground = {"default:dirt_with_grass", "default:dirt_with_coniferous_litter", "default:dirt_with_rainforest_litter",
|
||||
|
@ -226,6 +257,38 @@ function voxeldungeon.utils.randomChances(chanceTable)
|
|||
end
|
||||
end
|
||||
|
||||
function voxeldungeon.utils.randomDecimal(upper, lower)
|
||||
upper = upper or 1
|
||||
lower = lower or 0
|
||||
|
||||
return lower + (math.random(0, 10000) / 10000) * (upper - lower)
|
||||
end
|
||||
|
||||
function voxeldungeon.utils.randomteleport(obj)
|
||||
for try = 1, 10 do
|
||||
local p = obj:get_pos()
|
||||
|
||||
local testpos =
|
||||
{
|
||||
x = p.x + math.random(-100, 100),
|
||||
y = p.y + 0.5,
|
||||
z = p.z + math.random(-100, 100)
|
||||
}
|
||||
|
||||
if not minetest.registered_nodes[minetest.get_node(testpos).name].walkable then
|
||||
obj:set_pos(testpos)
|
||||
|
||||
minetest.sound_play("voxeldungeon_teleport",
|
||||
{
|
||||
pos = obj:get_pos(),
|
||||
gain = 1.0,
|
||||
max_hear_distance = 32,
|
||||
})
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function voxeldungeon.utils.round(num)
|
||||
return math.floor(num + .5)
|
||||
end
|
||||
|
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 350 B |
After Width: | Height: | Size: 275 B |
After Width: | Height: | Size: 587 B |
After Width: | Height: | Size: 630 B |
After Width: | Height: | Size: 280 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 219 B |
After Width: | Height: | Size: 265 B |
After Width: | Height: | Size: 295 B |
After Width: | Height: | Size: 316 B |
After Width: | Height: | Size: 339 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 418 B |
After Width: | Height: | Size: 503 B |
After Width: | Height: | Size: 628 B |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 258 B |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 439 B |
After Width: | Height: | Size: 233 B |
After Width: | Height: | Size: 498 B |
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 268 B |
Before Width: | Height: | Size: 265 B After Width: | Height: | Size: 265 B |
Before Width: | Height: | Size: 258 B After Width: | Height: | Size: 258 B |
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B |
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 278 B After Width: | Height: | Size: 278 B |
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 440 B |
Before Width: | Height: | Size: 276 B After Width: | Height: | Size: 276 B |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 326 B |
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |