X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=mods%2Ftnt%2Finit.lua;h=b5457e9a2359ec02a74d2bf2df1e5d16bce61587;hb=48aa89197636250b3e494e9124c7c5c6e2d63dea;hp=93c8197222779acebd18ac7f23e9c8cfb767cf18;hpb=df748cc7e7bf49efa3079838c4a812821eb2b7d5;p=Crafter.git diff --git a/mods/tnt/init.lua b/mods/tnt/init.lua index 93c8197..b5457e9 100644 --- a/mods/tnt/init.lua +++ b/mods/tnt/init.lua @@ -1,18 +1,9 @@ ---here is where tnt is defined -local function extreme_tnt(pos,range) +local minetest,type,vector,math,ipairs,os = +minetest,type,vector,math,ipairs,os + + +local function extreme_tnt(pos,range,explosion_type) local pos = vector.floor(vector.add(pos,0.5)) - - --kill - --[[ - for _,object in ipairs(minetest.get_objects_inside_radius(pos, range)) do - if object:is_player() then - object:set_hp(-50) - elseif object:get_luaentity() and object:get_luaentity().name == "__builtin:item" then - object:remove() - end - end - ]]-- - local delay = 0 for x=-1,0 do for y=-1,0 do @@ -46,31 +37,7 @@ local function extreme_tnt(pos,range) minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = range*range*range}) end ---[[ -minetest.register_globalstep(function(dtime) - --collection - for _,player in ipairs(minetest.get_connected_players()) do - local pos = player:get_pos() - pos.y = pos.y + player:get_properties().eye_height - local look_dir = player:get_look_dir() - look_dir = vector.multiply(look_dir,7) - local pos2 = vector.add(pos,look_dir) - - local ray = minetest.raycast(pos, pos2, false, false) - if ray then - print("------------------------------------------------------------") - for pointed_thing in ray do - print(minetest.get_node(pointed_thing.under).name) - --if pointed_thing then - -- return({under=pointed_thing.under,above=pointed_thing.above}) - --end - end - end - end -end) -]]-- --use raycasting to create actual explosion -local old_node_table local n_pos local node2 local ray @@ -78,61 +45,97 @@ local stop local found local positional_data local pos2 = vector.new(0,0,0) -function tnt(pos,range) - local in_node = minetest.get_node(pos).name - local in_water = ( in_node == "main:water" or minetest.get_node(pos).name == "main:waterflow") - local min = vector.add(pos,range) - local max = vector.subtract(pos,range) - local vm = minetest.get_voxel_manip() - local emin, emax = vm:read_from_map(min,max) - local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} - local data = vm:get_data() - - local air = minetest.get_content_id("air") - local content_id = minetest.get_name_from_content_id - - local insert = table.insert - - vm:get_light_data() - - - +local in_node +local in_water +local min +local max +local vm +local emin +local emax +local area +local data +local air = minetest.get_content_id("air") +local content_id = minetest.get_name_from_content_id +local distance +local item +local ppos +local obj +local do_it +local in_node +local clear +local power +local dir +local force +local hp +local explosion_force +local explosion_depletion +local range_calc +local boom_time = minetest.get_us_time()/1000000 +local digging_nodes = { + ["utility:chest_open"] = true, + ["utility:chest"] = true, + ["utility:furnace_active"] = true, + ["utility:furnace"] = true, +} +function tnt(pos,range,explosion_type) + in_node = minetest.get_node(pos).name + in_water = ( in_node == "main:water" or minetest.get_node(pos).name == "main:waterflow") + min = vector.add(pos,range) + max = vector.subtract(pos,range) + vm = minetest.get_voxel_manip(min,max) + emin, emax = vm:read_from_map(min,max) + area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} + data = vm:get_data() + if in_water == false then + vm:get_light_data() + range_calc = range/100 + explosion_depletion = range/2 --raycast explosion for x=-range, range do for y=-range, range do for z=-range, range do - local distance = vector.distance(pos2, vector.new(x,y,z)) - if distance <= range and distance >= range-1 then + distance = vector.distance(pos2, vector.new(x,y,z)) + if distance <= range and distance >= range-1 then ray = minetest.raycast(pos, vector.new(pos.x+x,pos.y+y,pos.z+z), false, false) - + explosion_force = range for pointed_thing in ray do - n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z) - node2 = content_id(data[n_pos]) - - if node2 == "nether:obsidian" or node2 == "nether:bedrock" then - break - elseif node2 == "tnt:tnt" then - data[n_pos] = air - local obj = minetest.add_entity(vector.new(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z), "tnt:tnt",minetest.serialize({do_ignition_particles=true,timer = math.random()})) - else - data[n_pos] = air - minetest.after(0, function(pointed_thing) - minetest.check_for_falling(vector.new(pointed_thing.under.x,pointed_thing.under.y+1,pointed_thing.under.z)) - end,pointed_thing) - if math.random()>0.999 then - if n ~= "nether:obsidian" and n ~= "nether:bedrock" then - local item = minetest.get_node_drops(n, "main:diamondpick")[1] - local ppos = vector.new(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z) - local obj = minetest.add_item(ppos, item) - if obj then - local power = (range - vector.distance(pos,ppos))*2 - local dir = vector.subtract(ppos,pos) - local force = vector.multiply(dir,power) - obj:set_velocity(force) + explosion_force = explosion_force - math.random() + if pointed_thing and explosion_force >= explosion_depletion then + n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z) + + if n_pos and data[n_pos] then + node2 = content_id(data[n_pos]) + + if node2 == "nether:obsidian" or node2 == "nether:bedrock" then + break + elseif digging_nodes[node2] then + minetest.dig_node({x=pointed_thing.under.x,y=pointed_thing.under.y,z=pointed_thing.under.z}) + data[n_pos] = air + elseif node2 == "tnt:tnt" then + data[n_pos] = air + minetest.add_entity({x=pointed_thing.under.x,y=pointed_thing.under.y,z=pointed_thing.under.z}, "tnt:tnt",minetest.serialize({do_ignition_particles=true,timer = math.random()})) + elseif not string.match(node2, "mob_spawners:") then + data[n_pos] = air + + minetest.after(0, function(pointed_thing) + minetest.check_for_falling({x=pointed_thing.under.x,y=pointed_thing.under.y+1,z=pointed_thing.under.z}) + end,pointed_thing) + if range_calc < 1 and math.random() > 0.9 + range_calc then + item = minetest.get_node_drops(node2, "main:diamondpick")[1] + ppos = {x=pointed_thing.under.x,y=pointed_thing.under.y,z=pointed_thing.under.z} + obj = minetest.add_item(ppos, item) + if obj then + power = (range - vector.distance(pos,ppos))*2 + dir = vector.subtract(ppos,pos) + force = vector.multiply(dir,power) + obj:set_velocity(force) + end end end end + else + break end end end @@ -143,26 +146,28 @@ function tnt(pos,range) vm:update_liquids() vm:write_to_map() end - - minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = range*range}) --hear twice as far away + if minetest.get_us_time()/1000000 - boom_time >= 0.1 then + boom_time = minetest.get_us_time()/1000000 + minetest.sound_play("tnt_explode", {pos = pos, gain = 1.0, max_hear_distance = 64}) --hear twice as far away + end --throw players and items for _,object in ipairs(minetest.get_objects_inside_radius(pos, range)) do if object:is_player() or (object:get_luaentity() and (object:get_luaentity().name == "__builtin:item" or object:get_luaentity().name == "tnt:tnt" or object:get_luaentity().is_mob == true)) then - local do_it = true + do_it = true if not object:is_player() and object:get_luaentity().name == "tnt:tnt" then - local in_node = minetest.get_node(object:get_pos()).name + in_node = minetest.get_node(object:get_pos()).name if ( in_node == "main:water" or in_node == "main:waterflow") then do_it = false end end if do_it == true then - local ppos = object:get_pos() + ppos = object:get_pos() if object:is_player() then ppos.y = ppos.y + 1 end ray = minetest.raycast(pos, ppos, false, false) - local clear = true + clear = true for pointed_thing in ray do n_pos = area:index(pointed_thing.under.x,pointed_thing.under.y,pointed_thing.under.z) node2 = content_id(data[n_pos]) @@ -171,13 +176,12 @@ function tnt(pos,range) end end if clear == true then - local power = (range - vector.distance(pos,ppos))*8 - - local dir = vector.direction(pos,ppos) - local force = vector.multiply(dir,power) + power = (range - vector.distance(pos,ppos))*10 + dir = vector.direction(pos,ppos) + force = vector.multiply(dir,power) if object:is_player() then --damage the player - local hp = object:get_hp() + hp = object:get_hp() if hp > 0 then --object:set_hp(hp - math.floor(power*2)) object:punch(object, 2, @@ -196,8 +200,10 @@ function tnt(pos,range) full_punch_interval=1.5, damage_groups = {damage=math.floor(power)}, }) - object:set_velocity(force) + elseif object:get_luaentity().name == "__builtin:item" then + object:get_luaentity().poll_timer = 0 end + object:set_velocity(force) end end end @@ -205,14 +211,13 @@ function tnt(pos,range) end --stop client from lagging - local particle = range - if particle > 15 then - particle = 15 + if range > 15 then + range = 15 end minetest.add_particlespawner({ - amount = particle*particle, + amount = range, time = 0.001, minpos = pos, maxpos = pos, @@ -231,6 +236,68 @@ function tnt(pos,range) }) end +local pos +local vel +local range +local tnt_boom = function(self,dtime) + self.timer = self.timer - dtime + if not self.shot or not self.redstone_activated then + vel = self.object:getvelocity() + vel = vector.multiply(vel,-0.05) + self.object:add_velocity(vector.new(vel.x,0,vel.z)) + end + if self.timer <= 0 then + if not self.range then + self.range = 7 + end + pos = self.object:get_pos() + range = self.range + self.object:remove() + tnt(pos,range) + end +end +local activation = function(self, staticdata, dtime_s) + self.object:set_armor_groups({immortal = 1}) + self.object:set_velocity({x = math.random(-3,3), y = 3, z = math.random(-3,3)}) + self.object:set_acceleration({x = 0, y = -9.81, z = 0}) + if string.sub(staticdata, 1, string.len("return")) == "return" then + local data = minetest.deserialize(staticdata) + if data and type(data) == "table" then + self.range = data.range + self.timer = data.timer + self.exploded = data.exploded + end + end + if self.timer == self.timer_max then + minetest.add_particlespawner({ + amount = 10, + time = 0, + minpos = vector.new(0,0.5,0), + minpos = vector.new(0,0.5,0), + minvel = vector.new(-0.5,1,-0.5), + maxvel = vector.new(0.5,5,0.5), + minacc = {x=0, y=0, z=0}, + maxacc = {x=0, y=0, z=0}, + minexptime = 0.5, + maxexptime = 1.0, + minsize = 1, + maxsize = 2, + collisiondetection = false, + vertical = false, + texture = "smoke.png", + attached = self.object, + }) + minetest.sound_play("tnt_ignite", {object = self.object, gain = 1.0, max_hear_distance = 64}) + end +end + +local static = function(self) + return minetest.serialize({ + range = self.range, + timer = self.timer, + exploded = self.exploded, + }) +end minetest.register_entity("tnt:tnt", { initial_properties = { @@ -251,74 +318,27 @@ minetest.register_entity("tnt:tnt", { timer_max = 5, --this has to be equal to timer range = 7, get_staticdata = function(self) - return minetest.serialize({ - range = self.range, - timer = self.timer, - exploded = self.exploded, - }) + return(static(self)) end, on_activate = function(self, staticdata, dtime_s) - self.object:set_armor_groups({immortal = 1}) - self.object:set_velocity({x = math.random(-3,3), y = 3, z = math.random(-3,3)}) - self.object:set_acceleration({x = 0, y = -9.81, z = 0}) - if string.sub(staticdata, 1, string.len("return")) == "return" then - local data = minetest.deserialize(staticdata) - if data and type(data) == "table" then - self.range = data.range - self.timer = data.timer - self.exploded = data.exploded - end - end - if self.timer == self.timer_max then - minetest.add_particlespawner({ - amount = 10, - time = 0, - minpos = vector.new(0,0.5,0), - minpos = vector.new(0,0.5,0), - minvel = vector.new(-0.5,1,-0.5), - maxvel = vector.new(0.5,5,0.5), - minacc = {x=0, y=0, z=0}, - maxacc = {x=0, y=0, z=0}, - minexptime = 0.5, - maxexptime = 1.0, - minsize = 1, - maxsize = 2, - collisiondetection = false, - vertical = false, - texture = "smoke.png", - attached = self.object, - }) - minetest.sound_play("tnt_ignite", {object = self.object, gain = 1.0, max_hear_distance = self.range*self.range*self.range}) - end + activation(self, staticdata, dtime_s) end, on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) - local obj = minetest.add_item(self.object:get_pos(), "tnt:tnt") + minetest.throw_item(self.object:get_pos(), "tnt:tnt") self.object:remove() end, sound_played = false, on_step = function(self, dtime) - self.timer = self.timer - dtime - if not self.shot or not self.redstone_activated then - local vel = self.object:getvelocity() - vel = vector.multiply(vel,-0.05) - self.object:add_velocity(vector.new(vel.x,0,vel.z)) - end - if self.timer <= 0 then - if not self.range then - self.range = 7 - end - tnt(self.object:get_pos(),self.range) - self.object:remove() - end + tnt_boom(self,dtime) end, }) minetest.register_node("tnt:tnt", { - description = "Cobblestone", + description = "TNT", tiles = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png", "tnt_side.png", "tnt_side.png", "tnt_side.png"}, @@ -326,21 +346,21 @@ minetest.register_node("tnt:tnt", { sounds = main.stoneSound(), redstone_activation = function(pos) local obj = minetest.add_entity(pos,"tnt:tnt") - local range = 7 + local range = 4 obj:get_luaentity().range = range obj:get_luaentity().redstone_activated = true minetest.remove_node(pos) end, on_punch = function(pos, node, puncher, pointed_thing) local obj = minetest.add_entity(pos,"tnt:tnt") - local range = 7 + local range = 4 obj:get_luaentity().range = range minetest.remove_node(pos) end, }) minetest.register_node("tnt:uranium_tnt", { - description = "Cobblestone", + description = "Uranium TNT", tiles = {"tnt_top.png^[colorize:green:100", "tnt_bottom.png^[colorize:green:100", "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100", "tnt_side.png^[colorize:green:100"}, @@ -358,7 +378,7 @@ minetest.register_node("tnt:uranium_tnt", { }) minetest.register_node("tnt:uh_oh", { - description = "Cobblestone", + description = "Uh Oh", tiles = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png", "tnt_side.png", "tnt_side.png", "tnt_side.png"},