From 3ebdae5ea1bacb453af241e1fc294ae8ff3720ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Ryb=C3=A1rsky?= Date: Tue, 12 Jul 2022 10:20:50 +0200 Subject: [PATCH] split it into separate files --- gravityuse.lua | 160 ------- init.lua | 592 ++--------------------- mod.conf | 2 +- models/{torret.blend => turret.blend} | Bin models/{torret1.obj => turret1.obj} | 0 models/{torret2.obj => turret2.obj} | 0 other.lua | 637 ------------------------ powerball.lua | 147 ------ scripts/buildingblocks.lua | 101 ++++ scripts/button.lua | 51 ++ scripts/cake.lua | 43 ++ scripts/camera.lua | 73 +++ scripts/checkpoint.lua | 64 +++ scripts/cubespawners.lua | 101 ++++ scripts/damageblock.lua | 63 +++ scripts/delayer.lua | 78 +++ scripts/doors.lua | 322 +++++++++++++ scripts/editingtools.lua | 64 +++ scripts/fizzlers.lua | 88 ++++ scripts/gravityuse.lua | 173 +++++++ scripts/objectdestroyer.lua | 51 ++ scripts/portalgun.lua | 664 ++++++++++++++++++++++++++ scripts/portaltarget.lua | 52 ++ scripts/powerball.lua | 86 ++++ scripts/powerballspawner.lua | 95 ++++ scripts/powerballtarget.lua | 27 ++ scripts/pressureplatforms.lua | 236 +++++++++ scripts/signs.lua | 202 ++++++++ scripts/toxicwater.lua | 58 +++ scripts/turrets.lua | 257 ++++++++++ scripts/warntape.lua | 32 ++ scripts/weightedstoragecube.lua | 88 ++++ stuff.lua | 606 ----------------------- textures/weightedcompanioncube.png | Bin 0 -> 11549 bytes textures/weightedcompanioncube2.png | Bin 0 -> 11701 bytes textures/weightedcompanioncube3.png | Bin 0 -> 11661 bytes textures/weightedcompanioncube4.png | Bin 0 -> 11699 bytes weightedstoragecube.lua | 362 -------------- 38 files changed, 3107 insertions(+), 2468 deletions(-) delete mode 100644 gravityuse.lua rename models/{torret.blend => turret.blend} (100%) rename models/{torret1.obj => turret1.obj} (100%) rename models/{torret2.obj => turret2.obj} (100%) delete mode 100644 other.lua delete mode 100644 powerball.lua create mode 100644 scripts/buildingblocks.lua create mode 100644 scripts/button.lua create mode 100644 scripts/cake.lua create mode 100644 scripts/camera.lua create mode 100644 scripts/checkpoint.lua create mode 100644 scripts/cubespawners.lua create mode 100644 scripts/damageblock.lua create mode 100644 scripts/delayer.lua create mode 100644 scripts/doors.lua create mode 100644 scripts/editingtools.lua create mode 100644 scripts/fizzlers.lua create mode 100644 scripts/gravityuse.lua create mode 100644 scripts/objectdestroyer.lua create mode 100644 scripts/portalgun.lua create mode 100644 scripts/portaltarget.lua create mode 100644 scripts/powerball.lua create mode 100644 scripts/powerballspawner.lua create mode 100644 scripts/powerballtarget.lua create mode 100644 scripts/pressureplatforms.lua create mode 100644 scripts/signs.lua create mode 100644 scripts/toxicwater.lua create mode 100644 scripts/turrets.lua create mode 100644 scripts/warntape.lua create mode 100644 scripts/weightedstoragecube.lua delete mode 100644 stuff.lua create mode 100644 textures/weightedcompanioncube.png create mode 100644 textures/weightedcompanioncube2.png create mode 100644 textures/weightedcompanioncube3.png create mode 100644 textures/weightedcompanioncube4.png delete mode 100644 weightedstoragecube.lua diff --git a/gravityuse.lua b/gravityuse.lua deleted file mode 100644 index 4a3eaec..0000000 --- a/gravityuse.lua +++ /dev/null @@ -1,160 +0,0 @@ -portalgun_power={} -portalgun_power_tmp_power=0 - -function portalgun_gravity(itemstack, user, pointed_thing) - local ob=pointed_thing.ref - local at = ob:get_attach() - if at and at:get_luaentity() and at:get_luaentity().portalgun_power then - ob:set_detach() - local target = at:get_luaentity().target - if target and target:get_luaentity() and (target:get_luaentity().itemstring or target:get_luaentity().wsc) then - target:set_velocity({x=0, y=-1, z=0}) - target:set_acceleration({x=0, y=-8, z=0}) - end - return itemstack - end - if not ob:get_attach() and (ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().powerball~=1)) then - --if 4 blocks or closer to player - if vector.distance(ob:get_pos(),user:get_pos())<4 then - portalgun_power.user=user - portalgun_power.target=ob - if ob:is_player() then portalgun_power.player=1 end - local m=minetest.add_entity(ob:get_pos(), "portalgun:power") - ob:set_attach(m, "", {x=0,y=0,z=0}, {x=0,y=0,z=0}) - return itemstack - end - end - - - - - - - - return itemstack -end - -minetest.register_entity("portalgun:power",{ - hp_max = 100, - physical = false, - weight = 0, - collisionbox = {-0.2,-0.2,-0.2, 0.2,0.2,0.2}, - visual = "sprite", - visual_size = {x=1, y=1}, - textures = {"portalgun_gravity.png"}, - spritediv = {x=1, y=1}, - is_visible = true, - makes_footstep_sound = false, - automatic_rotate = 0, - timer=0, - time=0.1, - portalgun_power=1, - portalgun=1, - lifelime=100, -on_activate=function(self, staticdata) - if portalgun_power.user then - self.user=portalgun_power.user - self.target=portalgun_power.target - self.player=portalgun_power.player - portalgun_power={} - else - self.object:remove() - end - end, -on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir) - if self.target and self.target:get_attach() then - self.target:set_detach() - self.target:set_hp(0) - end - -end, -on_step= function(self, dtime) - self.timer=self.timer+dtime - if self.timer-0.5 then v2.x=0 end - if v2.y<0.5 and v2.y>-0.5 then v2.y=0 end - if v2.z<0.5 and v2.z>-0.5 then v2.z=0 end - - self.object:set_velocity(v2) - self.ltime=self.ltime-self.v - - if self.ltime0 then -- makes teleported stuff wont move back at same time (bug fix) - portalgun_portal[name].timer=portalgun_portal[name].timer-dtime - return self - end - - - if self.portal_max_use>0 then -- makes teleported stuff wont move back at same time (bug fix) - self.portal_max_use_time=self.portal_max_use_time+dtime - if self.portal_max_use>=portalgun_max_use_per_secund then - portal_delete(name,self.project) - return self - elseif self.portal_max_use_time>=portalgun_max_use_per_secund_time then - self.portal_max_use_time=0 - self.portal_max_use=0 - end - end - - local pos1=0 - local pos2=0 - local d1=0 - local d2=0 - if self.project==1 then - pos1=portalgun_portal[name].portal1_pos - pos2=portalgun_portal[name].portal2_pos - d1=portalgun_portal[name].portal1_dir - d2=portalgun_portal[name].portal2_dir - else - pos1=portalgun_portal[name].portal2_pos - pos2=portalgun_portal[name].portal1_pos - d1=portalgun_portal[name].portal2_dir - d2=portalgun_portal[name].portal1_dir - end - --- portalgun_front_of_field should fix teleport through walls, but is not working in all directions --- waiting with this issue - - - - if pos2~=0 and pos1~=0 then - for ii, ob in pairs(minetest.get_objects_inside_radius(pos1, self.area)) do - if pos2~=0 then --and portalgun_front_of_field(self.object,ob) - if (ob:is_player() ) or (ob:get_luaentity() and ob:get_luaentity().portalgun~=1 and ob:get_luaentity().name:find(":text",4)==nil) then - - - if ob:get_attach() then - ob:set_detach() - ob:set_acceleration({x=0, y=-10, z=0}) - end - --set velocity then teleport - local p=pos2 - local x=0 - local y=0 - local z=0 - local dis=2 - if p==nil or p.x==nil then - return self - end - - - if ob:is_player() then - local v=ob:get_player_velocity() - local player_name=ob:get_player_name() - portalgun_power.user=player_name - portalgun_power.target=ob - local vv={x=v.x,y=v.y,z=v.z} - -- get the highest velocity - dis=2 - if vv.x+vv.y+vv.z<=0.3 then - if self.small==true then - vv.x=1.4 - else - vv.x=2 - end - end - if vv.x+vv.y+vv.z==0 then vv.x=2 end - if vv.x<0 then vv.x=vv.x*-1 end - if vv.y<0 then vv.y=vv.y*-1 end - if vv.z<0 then vv.z=vv.z*-1 end - if vv.x>vv.z then vv.a=vv.x else vv.a=vv.z end - if vv.av.z then vv=v.x else vv=v.z end - if vv8 then - pos1.y=pos1.y+1 - end - if portalgun_portal[self.user].y>12 then - pos1.y=pos1.y+1 - end - if self.project==1 then - portalgun_portal[self.user].portal1_pos=pos1 - else - portalgun_portal[self.user].portal2_pos=pos1 - end - elseif string.find(d,"y",1)==nil and (portalgun_portal[self.user].x+portalgun_portal[self.user].z<2.5) then - self.area=1.2 - self.small=true - self.object:set_properties({visual_size = {x=0.7, y=0.7},}) - end - end, -on_step=portalgun_on_step, -}) -minetest.register_craftitem(":", { - description = "Portalgun", - range = 100, - inventory_image = "portalgun_gun0_rndr.png", - wield_image = "portalgun_gun0_rndr.png", - tool_capabilities = { - full_punch_interval = 0.5, - max_drop_level = 3, - groupcaps = { - fleshy = {times={[2]=0.80, [3]=0.40}, uses=100, maxlevel=3}, - oddly_breakable_by_hand = {times={[1]=1}, uses=100, maxlevel=1}, - }, - damage_groups = {fleshy=1}, - }, - on_place=function(itemstack, user, pointed_thing) - local node = minetest.get_node(pointed_thing.under) - if node.name=="portalgun:button"then - --use the item normally - minetest.item_place(itemstack, user, pointed_thing) - else - portalgun_onuse(itemstack, user, pointed_thing, 2) - end - return itemstack - end, - on_use = function(itemstack, user, pointed_thing) - --if pointing at turret then start breaking it - if pointed_thing.type=="node" then - local node=minetest.get_node(pointed_thing.under) - if node.name=="portalgun:turretgun" or node.name=="portalgun:turretgun2" then - minetest.remove_node(pointed_thing.under) - end - end - portalgun_onuse(itemstack, user, pointed_thing, 1) - return itemstack - end -}) - -local function rnd(r) -return math.floor(r+ 0.5) -end - -function portalgun_onuse(itemstack, user, pointed_thing, mode) -- using the gun - - if pointed_thing.type=="object" then - portalgun_gravity(itemstack, user, pointed_thing) - return itemstack - end - - local pos = user:get_pos() - local dir = user:get_look_dir() - local key = user:get_player_control() - local name=user:get_player_name() - local exist=0 - - local item=itemstack:to_table() - local ob={} - ob.project=1 - ob.lifelime=portalgun_lifelime - ob.portal1=0 - ob.portal2=0 - ob.portal1_dir=0 - ob.portal2_dir=0 - ob.portal2_pos=0 - ob.portal1_pos=0 - ob.user = user:get_player_name() - - if portalgun_portal[name]==nil then -- new portal profile - portalgun_portal[name]={lifelime=portalgun_lifelime,project=1,timer=0,portal1_active=false,portal2_active=false,portal1_use=0,portal2_use=0} - end - - if key.sneak then - portal_delete(name,0) - return itemstack - end - - pos.y=pos.y+1.5 - --- the project - - for i=1, portalgun_max_rage,0.5 do - local nname=minetest.get_node({x=pos.x+(dir.x*i), y=pos.y+(dir.y*i), z=pos.z+(dir.z*i)}).name - if minetest.registered_nodes[nname].walkable then - portalgun_portal[name].lifelime=portalgun_lifelime - - if not proportal_group_only and minetest.get_node_group(nname, "antiportal") > 0 then - minetest.sound_play("portalgun_error", {pos=pos,max_hear_distance = 5, gain = 3}) - return itemstack - elseif proportal_group_only and minetest.get_node_group(nname, "proportal") == 0 then - minetest.sound_play("portalgun_error", {pos=pos,max_hear_distance = 5, gain = 3}) - return itemstack - end - - if minetest.registered_nodes[minetest.get_node({x=rnd(pos.x+(dir.x*i)), y=rnd(pos.y+(dir.y*i)+1), z=rnd(pos.z+(dir.z*i))}).name].walkable==false and rnd(user:get_pos().y)>rnd(pos.y+(dir.y*i)) then - portalgun_setportal(pos,name,dir,i,mode,"y+") - return itemstack - elseif minetest.registered_nodes[minetest.get_node({x=rnd(pos.x+(dir.x*i)), y=rnd(pos.y+(dir.y*i)-1), z=rnd(pos.z+(dir.z*i))}).name].walkable==false and rnd(user:get_pos().y)rnd(pos.x+(dir.x*i)) then - portalgun_setportal(pos,name,dir,i,mode,"x+") - return itemstack - elseif minetest.registered_nodes[minetest.get_node({x=rnd(pos.x+(dir.x*i)), y=rnd(pos.y+(dir.y*i)), z=rnd(pos.z+(dir.z*i)-1)}).name].walkable==false and rnd(user:get_pos().z)rnd(pos.z+(dir.z*i)) then - portalgun_setportal(pos,name,dir,i,mode,"z+") - return itemstack - end - minetest.sound_play("portalgun_error", {pos=pos,max_hear_distance = 20, gain = 3}) - return itemstack - end - end - return itemstack -end - - - -function portalgun_setportal(pos,name,dir,i,mode,portal_dir) - local lpos={x=pos.x+(dir.x*(i-1)), y=pos.y+(dir.y*(i-1)), z=pos.z+(dir.z*(i-1))} -- last pos - local cpos={x=pos.x+(dir.x*i), y=pos.y+(dir.y*i), z=pos.z+(dir.z*i)} -- corrent poss - if portal_dir=="y+" then - cpos.y=(math.floor(cpos.y+ 0.5))+0.524 - elseif portal_dir=="y-" then - cpos.y=(math.floor(cpos.y+ 0.5))-0.524 - elseif portal_dir=="z+" then - cpos.z=(math.floor(cpos.z+ 0.5))+0.524 - elseif portal_dir=="z-" then - cpos.z=(math.floor(cpos.z+ 0.5))-0.524 - elseif portal_dir=="x+" then - cpos.x=(math.floor(cpos.x+ 0.5))+0.524 - elseif portal_dir=="x-" then - cpos.x=(math.floor(cpos.x+ 0.5))-0.524 - end - - if portal_dir=="x+" or portal_dir=="x-" then -- auto correct (place in center) - cpos.y=(math.floor(cpos.y+ 0.5)) - cpos.z=(math.floor(cpos.z+ 0.5)) - elseif portal_dir=="y+" or portal_dir=="y-" then - cpos.x=(math.floor(cpos.x+ 0.5)) - cpos.z=(math.floor(cpos.z+ 0.5)) - elseif portal_dir=="z+" or portal_dir=="z-" then - cpos.x=(math.floor(cpos.x+ 0.5)) - cpos.y=(math.floor(cpos.y+ 0.5)) - end - - if minetest.registered_nodes[minetest.get_node(cpos).name].walkable then - minetest.sound_play("portalgun_error", {pos=pos,max_hear_distance = 5, gain = 3}) - return false - end - - if string.find(portal_dir,"x",1) or string.find(portal_dir,"z",1) then-- auto correct (move from bottom / top) - local testpos1={x=cpos.x,y=cpos.y-1,z=cpos.z} - local testpos2={x=cpos.x,y=cpos.y+1,z=cpos.z} - if minetest.registered_nodes[minetest.get_node(testpos1).name].walkable - and minetest.registered_nodes[minetest.get_node(testpos2).name].walkable==false then - cpos.y=cpos.y+0.5 - elseif minetest.registered_nodes[minetest.get_node(testpos2).name].walkable - and minetest.registered_nodes[minetest.get_node(testpos1).name].walkable==false then - cpos.y=cpos.y-0.5 - end - end - - portalgun_portal_tmp_user=name - portalgun_portal[name].x=pos.x-lpos.x - portalgun_portal[name].y=pos.y-lpos.y - portalgun_portal[name].z=pos.z-lpos.z - portalgun_portal[name].project=mode - - if portalgun_portal[name].x<0 then - portalgun_portal[name].x=portalgun_portal[name].x*-1 - end - if portalgun_portal[name].z<0 then - portalgun_portal[name].z=portalgun_portal[name].z*-1 - end - - - - - - - if mode==1 then - portal_delete(name,1) - portalgun_portal[name].portal1_use=portalgun_portal[name].portal1_use+1 - portalgun_portal[name].portal1_dir=portal_dir - portalgun_portal[name].portal1_pos=cpos - portalgun_portal[name].portal1=minetest.add_entity(cpos, "portalgun:portal") - portalgun_portal[name].portal1_active=true - minetest.sound_play("portalgun_portalblue", {pos=cpos, max_hear_distance = 20, gain = 1}) - else - portal_delete(name,2) - portalgun_portal[name].portal2_use=portalgun_portal[name].portal2_use+1 - portalgun_portal[name].portal2_dir=portal_dir - portalgun_portal[name].portal2_pos=cpos - portalgun_portal[name].portal2=minetest.add_entity(cpos, "portalgun:portal") - portalgun_portal[name].portal2_active=true - minetest.sound_play("portalgun_portalorange", {pos=cpos,max_hear_distance = 20, gain = 1}) - end -end - -portalgun_front_of_field=function(ob,ob2) - local pos2=ob2:get_pos() - return vector.distance(ob:get_pos(),pos2)>vector.distance(portalgun_pointat(ob),pos2) -end - -portalgun_pointat=function(ob) - local pos=ob:get_pos() - local yaw=ob:get_yaw() - if yaw ~= yaw or type(yaw)~="number" then - yaw=0 - end - local z =math.sin(yaw) * -0.1 - local x =math.cos(yaw) * 0.1 - return {x=pos.x+x,y=pos.y,z=pos.z+z} -end + --portalgun + dofile(minetest.get_modpath("portalgun") .. "/scripts/portalgun.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/gravityuse.lua") + + --powerball + dofile(minetest.get_modpath("portalgun") .. "/scripts/powerball.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/powerballspawner.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/powerballtarget.lua") + + + --cubes + dofile(minetest.get_modpath("portalgun") .. "/scripts/weightedstoragecube.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/cubespawners.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/pressureplatforms.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/fizzlers.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/checkpoint.lua") + + --misc + dofile(minetest.get_modpath("portalgun") .. "/scripts/buildingblocks.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/warntape.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/cake.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/editingtools.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/portaltarget.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/signs.lua") + + --hazardous + dofile(minetest.get_modpath("portalgun") .. "/scripts/toxicwater.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/turrets.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/camera.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/damageblock.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/objectdestroyer.lua") + + --logic + dofile(minetest.get_modpath("portalgun") .. "/scripts/delayer.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/button.lua") + dofile(minetest.get_modpath("portalgun") .. "/scripts/doors.lua") \ No newline at end of file diff --git a/mod.conf b/mod.conf index f1cc4ca..3b628e0 100644 --- a/mod.conf +++ b/mod.conf @@ -1,3 +1,3 @@ name = portalgun description = Portals and stuff -optional_depends = mesecons \ No newline at end of file +depends = mesecons \ No newline at end of file diff --git a/models/torret.blend b/models/turret.blend similarity index 100% rename from models/torret.blend rename to models/turret.blend diff --git a/models/torret1.obj b/models/turret1.obj similarity index 100% rename from models/torret1.obj rename to models/turret1.obj diff --git a/models/torret2.obj b/models/turret2.obj similarity index 100% rename from models/torret2.obj rename to models/turret2.obj diff --git a/other.lua b/other.lua deleted file mode 100644 index d42a453..0000000 --- a/other.lua +++ /dev/null @@ -1,637 +0,0 @@ -local pgad_rules={{x = 1, y = 0, z = 0},{x =-1, y = 0, z = 0},{x = 0, y = 1, z = 0},{x = 0, y =-1, z = 0},{x = 0, y = 0, z = 1},{x = 0, y = 0, z =-1}} -stone_sounds = {} -stone_sounds.footstep = {name="stone_walk", gain=1.0} -stone_sounds.dug = {name="stone_break", gain=1.0} -stone_sounds.place = {name="block_place", gain=1.0} -glass_sounds = {} -glass_sounds.footstep = {name="glass_walk", gain=1.0} -glass_sounds.dug = {name="glass_break", gain=1.0} -glass_sounds.place = {name="block_place", gain=1.0} -wood_sounds = {} -wood_sounds.footstep = {name="wood_walk", gain=1.0} -wood_sounds.dug = {name="wood_break", gain=1.0} -wood_sounds.place = {name="block_place", gain=1.0} - -minetest.register_node("portalgun:cplps1", { - description = "Close player portal", - tiles = {"portalgun_gray.png"}, - groups = {mesecon=2,snappy = 3, not_in_creative_inventory=0}, - sounds = stone_sounds, - is_ground_content = false, - mesecons = {effector = { - action_on = function (pos, node) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 6)) do - if ob and ob:is_player() then - portal_delete(ob:get_player_name(),0) - end - end - minetest.swap_node(pos, {name="portalgun:cplps2"}) - minetest.after((2), function(pos) - minetest.swap_node(pos, {name="portalgun:cplps1"}) - end, pos) - - - return false - end, - }} -}) - -minetest.register_node("portalgun:cplps3", { - description = "Close player portal when player is near", - tiles = {"portalgun_gray.png"}, - groups = {snappy = 3, not_in_creative_inventory=0}, - sounds = stone_sounds, - is_ground_content = false, - --every 2 seconds, check if player is near and close portal if so - on_timer = function (pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 4)) do - if ob and ob:is_player() then - minetest.sound_play("portalgun_close", {pos=pos, gain=1.0, max_hear_distance = 10,}) - portal_delete(ob:get_player_name(),0) - end - --destroy Weighted storage cubes - --if name starts with '''portalgun:wsc''' - if ob and ob:get_luaentity() and ob:get_luaentity().name and string.sub(ob:get_luaentity().name,1,13) == "portalgun:wsc" then - ob:remove() - end - end - local timer = minetest.get_node_timer(pos) - timer:start(2) - return true - end, - after_place_node = function(pos, placer, itemstack, pointed_thing) - local timer = minetest.get_node_timer(pos) - timer:start(2) - end, -}) - -minetest.register_node("portalgun:cplps2", { - description = "Close player portal", - tiles = {"portalgun_gray.png^[colorize:#ffe85977"}, - groups = {mesecon=2,snappy = 3, not_in_creative_inventory=1}, - sounds = stone_sounds, - is_ground_content = false, - paramtype = "light", - light_source = 4, -}) - - - -minetest.register_node("portalgun:sign_v", { - description = "Sign V", - tiles = {"portalgun_v.png"}, - inventory_image = "portalgun_v.png", - drop="portalgun:sign_x", - drawtype = "nodebox", - groups = {mesecon=2,snappy = 3, not_in_creative_inventory=1}, - sounds = wood_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - light_source = 5, - node_box = { - type="fixed", - fixed={-0.5,-0.5,0.45,0.5,0.5,0.5}}, - mesecons = {effector = { - action_off = function (pos, node) - minetest.swap_node(pos, {name="portalgun:sign_x", param2=minetest.get_node(pos).param2}) - end, - }} -}) - - -minetest.register_node("portalgun:sign_x", { - description = "Sign X", - tiles = {"portalgun_x.png"}, - inventory_image = "portalgun_x.png", - drawtype = "nodebox", - groups = {mesecon=2,snappy = 3, not_in_creative_inventory=0}, - sounds = wood_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - light_source = 3, - node_box = { - type="fixed", - fixed={-0.5,-0.5,0.45,0.5,0.5,0.5}}, - mesecons = {effector = { - action_on = function (pos, node) - minetest.swap_node(pos, {name="portalgun:sign_v", param2=minetest.get_node(pos).param2}) - end, - }} -}) - - -local portaltarget_sig={ -{1,"portalgun_blue.png"}, -{2,"portalgun_orange.png"}, -} - -for ii = 1, #portaltarget_sig, 1 do - -minetest.register_node("portalgun:portaltarget_" .. portaltarget_sig[ii][1], { - description = "Portal target " .. portaltarget_sig[ii][1] , - tiles = {"portalgun_testblock.png^" .. portaltarget_sig[ii][2]}, - groups = {mesecon = 2,cracky=2}, - mesecons = {receptor = {state = "off"}}, - sounds = stone_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - on_timer = function (pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do - if ob:get_luaentity() and ob:get_luaentity().portalgun and ob:get_luaentity().project==portaltarget_sig[ii][1] then - mesecon.receptor_on(pos) - - return true - end - end - mesecon.receptor_off(pos) - return true - end, - on_construct = function(pos) - if not mesecon then return false end - minetest.get_node_timer(pos):start(2) - end, -}) -end - - - -minetest.register_node("portalgun:button", { - description = "Button", - tiles = {"portalgun_bu.png"}, - groups = {cracky = 3,mesecon=1}, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - selection_box = {type = "fixed",fixed = { -0.2, -0.5, -0.2, 0.2, 0.85, 0.2 }}, - sounds = stone_sounds, - mesecons = {receptor = {state = "off"}}, - on_rightclick = function(pos, node, clicker) - mesecon.receptor_on(pos) - minetest.get_node_timer(pos):start(2) - minetest.sound_play("button_press", {pos=pos,max_hear_distance = 10, gain = 1}) - end, - on_timer = function (pos, elapsed) - mesecon.receptor_off(pos) - end, - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.25, -0.5, -0.25, 0.25, 0.7, 0.25}, - {-0.125, 0.5, -0.125, 0.125, 0.77, 0.125}, - }} - - - -}) - -minetest.register_node("portalgun:dmgblock_1", { - description = "Damage block (hurts when not active)", - tiles = {"portalgun_powerwall.png"}, - groups = {cracky = 1,mesecon=2}, - drawtype="glasslike", - paramtype="light", - alpha = 50, - sunlight_propagates = true, - sounds = stone_sounds, - walkable=false, - damage_per_second = 5, - mesecons = {conductor = { - state = mesecon.state.off, - onstate = "portalgun:dmgblock_2", - rules = pgad_rules - }}, -}) -minetest.register_node("portalgun:dmgblock_2", { - description = "Damage block", - tiles = {"portalgun_gravity.png"}, - groups = {mesecon=2,not_in_creative_inventory=1}, - drawtype="airlike", - pointable=false, - sunlight_propagates = true, - drop="portalgun:dmgblock_1", - paramtype="light", - walkable=false, - mesecons = {conductor = { - state = mesecon.state.on, - offstate = "portalgun:dmgblock_1", - rules = pgad_rules - }}, -}) - - - - - - - - - - - - - -minetest.register_on_respawnplayer(function(player) - local name=player:get_player_name() - minetest.after(1, function(name) - if portalgun.checkpoints[name]~=nil then - player:move_to(portalgun.checkpoints[name]) - end - end, name) - -end) -minetest.register_on_leaveplayer(function(player) - local name=player:get_player_name() - if portalgun.checkpoints[name]~=nil then - portalgun.checkpoints[name]=nil - end -end) -minetest.register_node("portalgun:autocheckpoint", { - description = "Checkpoint (teleports to here on death)", - tiles = {"portalgun_checkpoint.png"}, - groups = {cracky = 3,not_in_creative_inventory=0}, - paramtype = "light", - sunlight_propagates = true, - light_source = 5, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type="fixed", - fixed={-0.5,-0.5,-0.5,0.5,-0.4,0.5}}, - on_construct = function(pos) - minetest.get_meta(pos):set_string("infotext","Checkpoint") - minetest.get_node_timer(pos):start(2) - end, - on_timer = function (pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do - if ob:is_player() then - local name=ob:get_player_name() - if portalgun.checkpoints[name]~=nil then - local cp=portalgun.checkpoints[name] - if cp.x==pos.x and cp.y==pos.y and cp.z==pos.z then - return true - end - end - portal_delete(name,0) - portalgun_portal[name]=nil - portalgun.checkpoints[name]=pos - minetest.sound_play("portalgun_checkpoint", {pos=pos,max_hear_distance = 5, gain = 1}) - minetest.chat_send_player(name, " You will spawn here next time you die") - end - end - return true - end, -}) - -minetest.register_node("portalgun:powerdoor1_1", { - description = "Power door", - inventory_image = "portalgun_powerwall.png", - wield_image = "portalgun_powerwall.png", - groups = {mesecon=1,unbreakable = 1,not_in_creative_inventory=0}, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - sounds = stone_sounds, - drawtype="nodebox", - alpha = 160, - node_box = { - type="fixed", - fixed={-0.5,-0.5,0.4,0.5,0.5,0.5}}, - tiles = { - { - name = "portalgun_powerwall1.png", - animation = { - type = "vertical_frames", - aspect_w = 16, - aspect_h = 16, - length = 0.2, - }, - }, - }, -after_place_node = function(pos, placer, itemstack) - local name=placer:get_player_name() - minetest.get_meta(pos):set_string("owner",name) - local p2=minetest.get_node(pos) - pos.y=pos.y+1 - local n=minetest.get_node(pos) - if n.name=="air" then - minetest.set_node(pos,{name="portalgun:powerdoor1_2",param2=p2.param2}) - minetest.get_meta(pos):set_string("owner",name) - end - end, -on_punch = function(pos, node, player, pointed_thing) - local meta = minetest.get_meta(pos); - if meta:get_string("owner")==player:get_player_name() then - minetest.node_dig(pos,minetest.get_node(pos),player) - pos.y=pos.y+1 - local un=minetest.get_node(pos).name - if un=="portalgun:powerdoor1_2" then - minetest.set_node(pos,{name="air"}) - end - pos.y=pos.y-1 - return true - end - end, - mesecons = {conductor = { - state = mesecon.state.off, - onstate = "portalgun:powerdoor2_1", - rules = pgad_rules - }}, -}) - -minetest.register_node("portalgun:powerdoor1_2", { - description = "Power door", - inventory_image = "portalgun_powerwall.png", - groups = {mesecon=1,unbreakable = 1,not_in_creative_inventory=1}, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - sounds = stone_sounds, - drawtype="nodebox", - alpha = 160, - node_box = { - type="fixed", - fixed={-0.5,-0.5,0.4,0.5,0.5,0.5}}, - tiles = { - { - name = "portalgun_powerwall1.png", - animation = { - type = "vertical_frames", - aspect_w = 16, - aspect_h = 16, - length = 0.2, - }, - }, - }, -on_punch = function(pos, node, player, pointed_thing) - local meta = minetest.get_meta(pos); - if meta:get_string("owner")==player:get_player_name() then - minetest.set_node(pos,{name="air"}) - pos.y=pos.y-1 - local un=minetest.get_node(pos).name - if un=="portalgun:powerdoor1_1" then - minetest.node_dig(pos,minetest.get_node(pos),player) - end - pos.y=pos.y+1 - return true - end - end, - mesecons = {conductor = { - state = mesecon.state.off, - onstate = "portalgun:powerdoor2_2", - rules = pgad_rules - }}, -}) - -minetest.register_node("portalgun:powerdoor2_1", { - description = "Power door", - inventory_image = "portalgun_powerwall.png", - groups = {unbreakable=1,mesecon=1,not_in_creative_inventory=1}, - paramtype = "light", - sunlight_propagates = true, - drawtype="airlike", - walkable = false, - pointable = false, - diggable = false, - mesecons = {conductor = { - state = mesecon.state.on, - offstate = "portalgun:powerdoor1_1", - rules = pgad_rules - }}, -}) - -minetest.register_node("portalgun:powerdoor2_2", { - description = "Power door", - inventory_image = "portalgun_powerwall.png", - groups = {unbreakable=1,mesecon=1,not_in_creative_inventory=1}, - paramtype = "light", - sunlight_propagates = true, - drawtype="airlike", - walkable = false, - pointable = false, - diggable = false, - mesecons = {conductor = { - state = mesecon.state.on, - offstate = "portalgun:powerdoor1_2", - rules = pgad_rules - }}, -}) - - -minetest.register_node("portalgun:delayer", { - description = "Delayer (Punsh to change time)", - tiles = {"portalgun_delayer.png","portalgun_testblock.png"}, - groups = {dig_immediate = 2,mesecon=1}, - sounds = stone_sounds, - paramtype = "light", - sunlight_propagates = true, - drawtype="nodebox", - node_box = { - type="fixed", - fixed={-0.5,-0.5,-0.5,0.5,-0.4,0.5}}, -on_punch = function(pos, node, player, pointed_thing) - if minetest.is_protected(pos, player:get_player_name())==false then - local meta = minetest.get_meta(pos) - local time=meta:get_int("time") - if time>=10 then time=0 end - meta:set_int("time",time+1) - meta:set_string("infotext","Delayer (" .. (time+1) ..")") - end - end, - - - on_construct = function(pos) - local meta = minetest.get_meta(pos) - meta:set_int("time",1) - meta:set_string("infotext","Delayer (1)") - meta:set_int("case",0) - end, - on_timer = function (pos, elapsed) - local meta = minetest.get_meta(pos) - if meta:get_int("case")==2 then - meta:set_int("case",0) - mesecon.receptor_off(pos) - end - if meta:get_int("case")==1 then - meta:set_int("case",2) - mesecon.receptor_on(pos) - minetest.get_node_timer(pos):start(meta:get_int("time")) - end - return false - end, - - mesecons = {effector = { - action_on = function (pos, node) - local meta = minetest.get_meta(pos) - if meta:get_int("case")==0 then - meta:set_int("case",1) - minetest.get_node_timer(pos):start(meta:get_int("time")) - end - - end, - }} -}) - - -minetest.register_node("portalgun:testblocks", { - description = "Trapblock", - tiles = {"portalgun_testblock.png"}, - groups = {cracky = 1,mesecon=2}, - sounds = stone_sounds, - mesecons = {conductor = { - state = mesecon.state.off, - onstate = "portalgun:testblocks2", - rules = pgad_rules - }}, -}) -minetest.register_node("portalgun:testblocks2", { - description = "Damage block", - tiles = {"portalgun_gravity.png"}, - groups = {mesecon=2,not_in_creative_inventory=1}, - drawtype="airlike", - pointable=false, - sunlight_propagates = true, - drop="portalgun:testblocks", - paramtype="light", - walkable=false, - mesecons = {conductor = { - state = mesecon.state.on, - offstate = "portalgun:testblocks", - rules = pgad_rules - }}, -}) - -minetest.register_node("portalgun:door_1", { - description = "Mesecon Door", - drop="portalgun:door_1", - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.5, -0.5, -0.125, 0.5, 0.5, 0.125}, - } - }, - tiles = {"portalgun_testblock.png"}, - groups = {mesecon=1,cracky = 1, level = 2, not_in_creative_inventory=0}, - sounds = stone_sounds, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - is_ground_content = false, -after_place_node = function(pos, placer, itemstack, pointed_thing) - local p={x=pos.x,y=pos.y+1,z=pos.z} - if minetest.registered_nodes[minetest.get_node(p).name].walkable then - return false - else - minetest.set_node(p, {name = "portalgun:door_2",param2=minetest.get_node(pos).param2}) - end - end, - - - - mesecons = {effector = { - action_on = function (pos, node) - local p={x=pos.x,y=pos.y+1,z=pos.z} - minetest.swap_node(p, {name="portalgun:door_open_2", param2=minetest.get_node(pos).param2}) - minetest.swap_node(pos, {name="portalgun:door_open_1", param2=minetest.get_node(pos).param2}) - minetest.sound_play("portalgun_door", {pos=pos, gain = 1, max_hear_distance = 5}) - end, - }}, -after_dig_node = function (pos, name, digger) - minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z}, {name = "air"}) - end, -}) - -minetest.register_node("portalgun:door_2", { - description = "Door 2-1", - drawtype = "nodebox", - drop="portalgun:door_1", - node_box = { - type = "fixed", - fixed = { - {-0.5, -0.5, -0.125, 0.5, 0.5, 0.125}, - } - }, - tiles = {"portalgun_testblock.png"}, - groups = {mesecon=1,cracky = 1, level = 2, not_in_creative_inventory=1}, - sounds = wood_sounds, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - is_ground_content = false, - mesecons = {effector = { - action_on = function (pos, node) - local p={x=pos.x,y=pos.y-1,z=pos.z} - minetest.swap_node(p, {name="portalgun:door_open_1", param2=minetest.get_node(pos).param2}) - minetest.swap_node(pos, {name="portalgun:door_open_2", param2=minetest.get_node(pos).param2}) - minetest.sound_play("portalgun_door", {pos=pos, gain = 1, max_hear_distance = 5}) - - end, - }}, -after_dig_node = function (pos, name, digger) - minetest.set_node({x=pos.x,y=pos.y-1,z=pos.z}, {name = "air"}) - end, -}) - -minetest.register_node("portalgun:door_open_1", { - description = "Door (open) 2-o-1", - drop="portalgun:door_1", - drawtype = "nodebox", - node_box = { - type = "fixed", - fixed = { - {0.41, -0.5, -0.124, 1.41, 0.5, 0.125}, - } - }, - tiles = {"portalgun_testblock.png"}, - groups = {mesecon=1,cracky = 1, level = 2, not_in_creative_inventory=1}, - sounds = wood_sounds, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - is_ground_content = false, -after_dig_node = function (pos, name, digger) - minetest.set_node({x=pos.x,y=pos.y+1,z=pos.z}, {name = "air"}) - end, - mesecons = {effector = { - action_off = function (pos, node) - local p={x=pos.x,y=pos.y+1,z=pos.z} - minetest.sound_play("portalgun_door", {pos=pos, gain = 1, max_hear_distance = 5}) - minetest.swap_node(p, {name="portalgun:door_2", param2=minetest.get_node(pos).param2}) - minetest.swap_node(pos, {name="portalgun:door_1", param2=minetest.get_node(pos).param2}) - end, - }} -}) - -minetest.register_node("portalgun:door_open_2", { - description = "Door (open) 2-o-1", - drawtype = "nodebox", - drop="portalgun:door_1", - node_box = { - type = "fixed", - fixed = { - {0.41, -0.5, -0.124, 1.41, 0.5, 0.125}, - } - }, - tiles = {"portalgun_testblock.png"}, - groups = {mesecon=1,cracky = 1, level = 2, not_in_creative_inventory=1}, - sounds = wood_sounds, - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - is_ground_content = false, -after_dig_node = function (pos, name, digger) - minetest.set_node({x=pos.x,y=pos.y-1,z=pos.z}, {name = "air"}) - end, - mesecons = {effector = { - action_off = function (pos, node) - local p={x=pos.x,y=pos.y-1,z=pos.z} - minetest.sound_play("portalgun_door", {pos=pos, gain = 1, max_hear_distance = 5}) - minetest.swap_node(p, {name="portalgun:door_1", param2=minetest.get_node(pos).param2}) - minetest.swap_node(pos, {name="portalgun:door_2", param2=minetest.get_node(pos).param2}) - end, - }} -}) diff --git a/powerball.lua b/powerball.lua deleted file mode 100644 index 2d495d6..0000000 --- a/powerball.lua +++ /dev/null @@ -1,147 +0,0 @@ -stone_sounds = {} -stone_sounds.footstep = {name="stone_walk", gain=1.0} -stone_sounds.dug = {name="stone_break", gain=1.0} -stone_sounds.place = {name="block_place", gain=1.0} -glass_sounds = {} -glass_sounds.footstep = {name="glass_walk", gain=1.0} -glass_sounds.dug = {name="glass_break", gain=1.0} -glass_sounds.place = {name="block_place", gain=1.0} -wood_sounds = {} -wood_sounds.footstep = {name="wood_walk", gain=1.0} -wood_sounds.dug = {name="wood_break", gain=1.0} -wood_sounds.place = {name="block_place", gain=1.0} -minetest.register_node("portalgun:powerballspawner", { - description = "Power ball spawner" , - tiles = {"steel.png","steel.png","steel.png","steel.png","steel.png","portalgun_powerballspawner.png"}, - groups = {cracky=2}, - sounds = glass_sounds, - is_ground_content = false, - paramtype2 = "facedir", - on_construct = function(pos) - minetest.get_node_timer(pos):start(10) - end, - on_timer = function (pos, elapsed) - local dir=minetest.get_node(pos).param2 - local v={x=0, y=0, z=0} - if dir==0 then v.z=-1 - elseif dir==1 then v.x=-1 - elseif dir==2 then v.z=1 - elseif dir==3 then v.x=1 - elseif dir==5 then v.y=-1 - elseif dir==4 then v.y=1 - else v.y = -1 - end - local pv={x=pos.x+v.x, y=pos.y+v.y, z=pos.z+v.z} - portalgun.new=1 - local m=minetest.add_entity(pv, "portalgun:powerball") - m:set_velocity({x=v.x*4, y=v.y*4, z=v.z*4}) - return true - end, -}) - -minetest.register_node("portalgun:powerballspawner2", { - description = "Power ball spawner (spawn on activate)" , - tiles = {"steel.png","steel.png","steel.png","steel.png","steel.png","portalgun_powerballspawner.png^[colorize:#aaaa0055"}, - groups = {cracky=2,mesecon=1}, - sounds = glass_sounds, - is_ground_content = false, - paramtype2 = "facedir", - on_place = minetest.rotate_node, - mesecons = {effector = { - action_on = function (pos, node) - local dir=minetest.get_node(pos).param2 - local v={x=0, y=0, z=0} - if dir==0 then v.z=-1 - elseif dir==1 then v.x=-1 - elseif dir==2 then v.z=1 - elseif dir==3 then v.x=1 - elseif dir==8 then v.y=-1 - elseif dir==4 then v.y=1 - end - local pv={x=pos.x+v.x, y=pos.y+v.y, z=pos.z+v.z} - portalgun.new=1 - local m=minetest.add_entity(pv, "portalgun:powerball") - m:set_velocity({x=v.x*4, y=v.y*4, z=v.z*4}) - end - }} -}) - - -minetest.register_entity("portalgun:powerball",{ - hp_max = 1000, - physical = true, - weight = 0, - collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4}, - visual = "sprite", - visual_size = {x=1.1, y=1.1}, - textures = {"portalgun_powrball.png"}, - initial_sprite_basepos = {x=0, y=0}, - is_visible = true, - makes_footstep_sound = false, - automatic_rotate = 0, - portalgun=2, - powerball=1, -on_activate= function(self, staticdata) - if portalgun.new==0 then - self.object:remove() - return self - end - portalgun.new=0 - local pos=self.object:get_pos() - self.sound=minetest.sound_play("portalgun_powerball", {pos=pos,max_hear_distance = 10, gain = 0.5}) - minetest.sound_play("portalgun_powerballbonce", {pos=pos,max_hear_distance = 10, gain = 1}) -end, -on_step= function(self, dtime) - self.timer=self.timer+dtime - if self.timer<0.2 then return self end - self.timer=0 - local pos=self.object:get_pos() - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do - if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().portalgun~=1 and ob:get_luaentity().wsc==nil and ob:get_luaentity().powerball~=1) then - ob:set_hp(0) - end - end - self.timer2=self.timer2+1 - self.timer3=self.timer3+1 - if self.timer3>=9 then - self.timer3=0 - minetest.sound_stop(self.sound) - self.sound=minetest.sound_play("portalgun_powerball", {pos=pos,max_hear_distance = 10, gain = 0.5}) - end - if self.timer2>40 then - minetest.sound_stop(self.sound) - self.object:set_hp(0) - return self - end - local v=self.object:get_velocity() - local nextn={x=pos.x+(v.x)/3, y=pos.y+(v.y)/3, z=pos.z+(v.z)/3} - local nname=minetest.get_node(nextn).name - if minetest.registered_nodes[nname].walkable then - - if nname=="portalgun:powerballtarget" and mesecon then - mesecon.receptor_on(nextn) - minetest.get_node_timer(nextn):start(5) - self.object:remove() - end - self.object:set_velocity({x=v.x*-1, y=v.y*-1, z=v.z*-1}) - minetest.sound_play("portalgun_powerballbonce", {pos=pos,max_hear_distance = 10, gain = 1}) - end - end, - timer=0, - timer2=0, - timer3=0, - sound={} -}) - -minetest.register_node("portalgun:powerballtarget", { - description = "Power ball target" , - tiles = {"portalgun_powerballstarget.png"}, - groups = {mesecon = 2,cracky=2}, - mesecons = {receptor = {state = "off"}}, - sounds = stone_sounds, - is_ground_content = false, - on_timer = function (pos, elapsed) - mesecon.receptor_off(pos) - return false - end, -}) diff --git a/scripts/buildingblocks.lua b/scripts/buildingblocks.lua new file mode 100644 index 0000000..d301a78 --- /dev/null +++ b/scripts/buildingblocks.lua @@ -0,0 +1,101 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +local pgad_rules = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 1, z = 0}, + {x = 0, y = -1, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1} +} +minetest.register_node( + "portalgun:testblock", + { + description = "Test block", + tiles = {"portalgun_testblock.png"}, + groups = {cracky = 1}, + sounds = stone_sounds + } +) + +minetest.register_node( + "portalgun:apb", + { + description = "Anti portal block", + tiles = {"portalgun_testblock.png^[colorize:#ffffffaa"}, + groups = {cracky = 3, antiportal = 1}, + sounds = stone_sounds + } +) + +minetest.register_node( + "portalgun:apg", + { + description = "Anti portal glass", + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = {"glass.png^[colorize:#ffffffaa"}, + groups = {cracky = 1, antiportal = 1}, + sounds = glass_sounds + } +) +minetest.register_node( + "portalgun:hard_glass", + { + description = "Hard glass", + drawtype = "glasslike", + paramtype = "light", + sunlight_propagates = true, + tiles = {"glass.png^[colorize:#ddddddaa"}, + groups = {cracky = 1}, + sounds = glass_sounds + } +) +minetest.register_node( + "portalgun:testblocks", + { + description = "Trapblock", + tiles = {"portalgun_testblock.png"}, + groups = {cracky = 1, mesecon = 2}, + sounds = stone_sounds, + mesecons = { + conductor = { + state = mesecon.state.off, + onstate = "portalgun:testblocks2", + rules = pgad_rules + } + } + } +) +minetest.register_node( + "portalgun:testblocks2", + { + description = "Air block", + tiles = {"portalgun_gravity.png"}, + groups = {mesecon = 2, not_in_creative_inventory = 1}, + drawtype = "airlike", + pointable = false, + sunlight_propagates = true, + drop = "portalgun:testblocks", + paramtype = "light", + walkable = false, + mesecons = { + conductor = { + state = mesecon.state.on, + offstate = "portalgun:testblocks", + rules = pgad_rules + } + } + } +) diff --git a/scripts/button.lua b/scripts/button.lua new file mode 100644 index 0000000..1f82f7d --- /dev/null +++ b/scripts/button.lua @@ -0,0 +1,51 @@ +local pgad_rules = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 1, z = 0}, + {x = 0, y = -1, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1} +} +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} + +minetest.register_node( + "portalgun:button", + { + description = "Button", + tiles = {"portalgun_bu.png"}, + groups = {cracky = 3, mesecon = 1}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + selection_box = {type = "fixed", fixed = {-0.2, -0.5, -0.2, 0.2, 0.85, 0.2}}, + sounds = stone_sounds, + mesecons = {receptor = {state = "off"}}, + on_rightclick = function(pos, node, clicker) + mesecon.receptor_on(pos) + minetest.get_node_timer(pos):start(2) + minetest.sound_play("button_press", {pos = pos, max_hear_distance = 10, gain = 1}) + end, + on_timer = function(pos, elapsed) + mesecon.receptor_off(pos) + end, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.25, -0.5, -0.25, 0.25, 0.7, 0.25}, + {-0.125, 0.5, -0.125, 0.125, 0.77, 0.125} + } + } + } +) diff --git a/scripts/cake.lua b/scripts/cake.lua new file mode 100644 index 0000000..dd9ee71 --- /dev/null +++ b/scripts/cake.lua @@ -0,0 +1,43 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:cake", + { + description = "Cake", + groups = {dig_immediate = 3, not_in_creative_inventory = 0}, + paramtype = "light", + sunlight_propagates = true, + selection_box = {type = "fixed", fixed = {-0.3, -0.5, -0.3, 0.3, 0, 0.3}}, + sounds = stone_sounds, + tiles = { + "dirt.png^portalgun_cake1.png", + "dirt.png^portalgun_cake2.png" + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.3125, -0.5, 0.375, 0.3125, -0.125, 0.4375}, + {-0.3125, -0.5, -0.4375, 0.3125, -0.125, -0.375}, + {-0.4375, -0.5, -0.3125, -0.375, -0.125, 0.3125}, + {0.375, -0.5, -0.3125, 0.4375, -0.125, 0.3125}, + {-0.375, -0.5, -0.375, 0.375, -0.125, 0.375}, + {-0.25, -0.5, 0.4375, 0.25, -0.125, 0.5}, + {-0.25, -0.5, -0.5, 0.25, -0.125, -0.4375}, + {0.4375, -0.5, -0.25, 0.5, -0.125, 0.25}, + {-0.5, -0.5, -0.25, -0.4375, -0.125, 0.25}, + {0, -0.125, -0.0625, 0.0625, 0.1875, 0} + } + } + } +) diff --git a/scripts/camera.lua b/scripts/camera.lua new file mode 100644 index 0000000..074172d --- /dev/null +++ b/scripts/camera.lua @@ -0,0 +1,73 @@ +stone_sounds = {} +stone_sounds.footstep = {name="stone_walk", gain=1.0} +stone_sounds.dug = {name="stone_break", gain=1.0} +stone_sounds.place = {name="block_place", gain=1.0} +glass_sounds = {} +glass_sounds.footstep = {name="glass_walk", gain=1.0} +glass_sounds.dug = {name="glass_break", gain=1.0} +glass_sounds.place = {name="block_place", gain=1.0} +wood_sounds = {} +wood_sounds.footstep = {name="wood_walk", gain=1.0} +wood_sounds.dug = {name="wood_break", gain=1.0} +wood_sounds.place = {name="block_place", gain=1.0} +minetest.register_node("portalgun:secam_off", { + description = "Security cam (off)" , + tiles = {"portalgun_scam.png"}, + drawtype = "nodebox", + walkable=false, + groups = {dig_immediate = 3}, + sounds = glass_sounds, + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + node_box = {type="fixed", + fixed={ {-0.2, -0.5, -0.2, 0.2, -0.4, 0.2}, + {-0.1, -0.2, -0.1, 0.1, -0.4, 0.1}} + }, + on_place = minetest.rotate_node, + on_construct = function(pos) + minetest.get_meta(pos):set_string("infotext","click to activate") + end, +on_rightclick = function(pos, node, player, itemstack, pointed_thing) + minetest.set_node(pos, {name ="portalgun:secam", param1 = node.param1, param2 = node.param2}) + minetest.get_node_timer(pos):start(1) +end, +}) +minetest.register_node("portalgun:secam", { + description = "Security cam", + tiles = {"portalgun_scam.png"}, + drawtype = "nodebox", + walkable=false, + groups = {dig_immediate = 3,stone=1,not_in_creative_inventory=1}, + sounds = glass_sounds, + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + drop="portalgun:secam_off", + node_box = {type="fixed", + fixed={ {-0.2, -0.5, -0.2, 0.2, -0.4, 0.2}, + {-0.1, -0.2, -0.1, 0.1, -0.4, 0.1}} + }, +on_timer=function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 10)) do + if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().itemstring==nil and ob:get_luaentity().portalgun==nil) then + if portalgun_visiable(pos,ob) then + local v=ob:get_pos() + if not ob:get_luaentity() then v.y=v.y+1 end + local s={x=(v.x-pos.x)*3,y=(v.y-pos.y)*3,z=(v.z-pos.z)*3} + local m=minetest.add_entity(pos, "portalgun:bullet1") + m:set_velocity(s) + m:set_acceleration(s) + minetest.sound_play("portalgun_bullet1", {pos=pos, gain = 1, max_hear_distance = 15,}) + minetest.after((math.random(1,9)*0.1), function(pos,s,v) + local m=minetest.add_entity(pos, "portalgun:bullet1") + m:set_velocity(s) + m:set_acceleration(s) + minetest.sound_play("portalgun_bullet1", {pos=pos, gain = 1, max_hear_distance = 15,}) + end, pos,s,v) + end + end + end + return true + end, +}) \ No newline at end of file diff --git a/scripts/checkpoint.lua b/scripts/checkpoint.lua new file mode 100644 index 0000000..645b703 --- /dev/null +++ b/scripts/checkpoint.lua @@ -0,0 +1,64 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +checkpoints={} +minetest.register_node("portalgun:autocheckpoint", { + description = "Checkpoint (teleports to here on death)", + tiles = {"portalgun_checkpoint.png"}, + groups = {cracky = 3,not_in_creative_inventory=0}, + paramtype = "light", + sunlight_propagates = true, + light_source = 5, + sounds = stone_sounds, + drawtype="nodebox", + node_box = { + type="fixed", + fixed={-0.5,-0.5,-0.5,0.5,-0.4,0.5}}, + on_construct = function(pos) + minetest.get_meta(pos):set_string("infotext","Checkpoint") + minetest.get_node_timer(pos):start(2) + end, + on_timer = function (pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + if ob:is_player() then + local name=ob:get_player_name() + if checkpoints[name]~=nil then + local cp=checkpoints[name] + if cp.x==pos.x and cp.y==pos.y and cp.z==pos.z then + return true + end + end + portal_delete(name,0) + portalgun_portal[name]=nil + checkpoints[name]=pos + minetest.sound_play("portalgun_checkpoint", {pos=pos,max_hear_distance = 5, gain = 1}) + minetest.chat_send_player(name, " You will spawn here next time you die") + end + end + return true + end, +}) +minetest.register_on_respawnplayer(function(player) + local name=player:get_player_name() + minetest.after(1, function(name) + if checkpoints[name]~=nil then + player:move_to(checkpoints[name]) + end + end, name) + +end) +minetest.register_on_leaveplayer(function(player) + local name=player:get_player_name() + if checkpoints[name]~=nil then + checkpoints[name]=nil + end +end) \ No newline at end of file diff --git a/scripts/cubespawners.lua b/scripts/cubespawners.lua new file mode 100644 index 0000000..e51e07e --- /dev/null +++ b/scripts/cubespawners.lua @@ -0,0 +1,101 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +new = 0 +local ptgwsc = { + {"weightedstoragecube.png", "portalgun_presplat.png", "(blue)"}, + {"weightedstoragecube2.png", "portalgun_presplat2.png", "(orange)"}, + {"weightedstoragecube3.png", "portalgun_presplat3.png", "(yellow)"}, + {"weightedstoragecube4.png", "portalgun_presplat4.png", "(green)"}, + {"weightedcompanioncube.png", "portalgun_presplat.png", "(blue companion)"}, + {"weightedcompanioncube2.png", "portalgun_presplat2.png", "(orange companion)"}, + {"weightedcompanioncube3.png", "portalgun_presplat3.png", "(yellow companion)"}, + {"weightedcompanioncube4.png", "portalgun_presplat4.png", "(green companion)"} +} + +for ii = 1, #ptgwsc, 1 do + minetest.register_node( + "portalgun:wscspawner2_" .. ii, + { + description = "Weighted storage cube spawner2 " .. ptgwsc[ii][3], + tiles = {"steel.png", "steel.png", "steel.png", "steel.png", "steel.png", ptgwsc[ii][1]}, + groups = {cracky = 2, mesecon_receptor_off = 1, mesecon_effector_off = 1}, + sounds = glass_sounds, + is_ground_content = false, + paramtype2 = "facedir", + mesecons = { + receptor = {state = "off"}, + effector = { + action_on = function(pos, node) + local dir = minetest.get_node(pos).param2 + local v = {x = 0, y = 0, z = 0} + if dir == 0 then + v.z = -1 + elseif dir == 1 then + v.x = -1.2 + elseif dir == 2 then + v.z = 1.2 + elseif dir == 3 then + v.x = 1.2 + elseif dir == 8 then + v.y = -1.2 + elseif dir == 4 then + v.y = 1.2 + end + local pv = {x = pos.x + v.x, y = pos.y + v.y, z = pos.z + v.z} + new = 1 + local m = minetest.add_entity(pv, "portalgun:wsc" .. ii) + m:set_acceleration({x = 0, y = -10, z = 0}) + end + } + } + } + ) + minetest.register_node( + "portalgun:wscspawner" .. ii, + { + description = "Weighted storage cube spawner " .. ptgwsc[ii][3], + tiles = {ptgwsc[ii][1]}, + groups = {cracky = 1, not_in_creative_inventory = 0}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + light_source = 14, + sounds = stone_sounds, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, + {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, + {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, + {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, + {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(5) + end, + on_timer = function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 40)) do + if ob:get_luaentity() and ob:get_luaentity().wsc == ii then + return true + end + end + new = 1 + local m = minetest.add_entity(pos, "portalgun:wsc" .. ii) + m:set_acceleration({x = 0, y = -10, z = 0}) + return true + end + } + ) +end -- of for # diff --git a/scripts/damageblock.lua b/scripts/damageblock.lua new file mode 100644 index 0000000..57681dd --- /dev/null +++ b/scripts/damageblock.lua @@ -0,0 +1,63 @@ +local pgad_rules = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 1, z = 0}, + {x = 0, y = -1, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1} +} +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:dmgblock_1", + { + description = "Damage block (hurts when not active)", + tiles = {"portalgun_powerwall.png"}, + groups = {cracky = 1, mesecon = 2}, + drawtype = "glasslike", + paramtype = "light", + alpha = 50, + sunlight_propagates = true, + sounds = stone_sounds, + walkable = false, + damage_per_second = 5, + mesecons = { + conductor = { + state = mesecon.state.off, + onstate = "portalgun:dmgblock_2", + rules = pgad_rules + } + } + } +) +minetest.register_node( + "portalgun:dmgblock_2", + { + description = "Damage block", + tiles = {"portalgun_gravity.png"}, + groups = {mesecon = 2, not_in_creative_inventory = 1}, + drawtype = "airlike", + pointable = false, + sunlight_propagates = true, + drop = "portalgun:dmgblock_1", + paramtype = "light", + walkable = false, + mesecons = { + conductor = { + state = mesecon.state.on, + offstate = "portalgun:dmgblock_1", + rules = pgad_rules + } + } + } +) diff --git a/scripts/delayer.lua b/scripts/delayer.lua new file mode 100644 index 0000000..08df39d --- /dev/null +++ b/scripts/delayer.lua @@ -0,0 +1,78 @@ +local pgad_rules = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 1, z = 0}, + {x = 0, y = -1, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1} +} +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} + +minetest.register_node( + "portalgun:delayer", + { + description = "Delayer (Punsh to change time)", + tiles = {"portalgun_delayer.png", "portalgun_testblock.png"}, + groups = {dig_immediate = 2, mesecon = 1}, + sounds = stone_sounds, + paramtype = "light", + sunlight_propagates = true, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, -0.4, 0.5} + }, + on_punch = function(pos, node, player, pointed_thing) + if minetest.is_protected(pos, player:get_player_name()) == false then + local meta = minetest.get_meta(pos) + local time = meta:get_int("time") + if time >= 10 then + time = 0 + end + meta:set_int("time", time + 1) + meta:set_string("infotext", "Delayer (" .. (time + 1) .. ")") + end + end, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_int("time", 1) + meta:set_string("infotext", "Delayer (1)") + meta:set_int("case", 0) + end, + on_timer = function(pos, elapsed) + local meta = minetest.get_meta(pos) + if meta:get_int("case") == 2 then + meta:set_int("case", 0) + mesecon.receptor_off(pos) + end + if meta:get_int("case") == 1 then + meta:set_int("case", 2) + mesecon.receptor_on(pos) + minetest.get_node_timer(pos):start(meta:get_int("time")) + end + return false + end, + mesecons = { + effector = { + action_on = function(pos, node) + local meta = minetest.get_meta(pos) + if meta:get_int("case") == 0 then + meta:set_int("case", 1) + minetest.get_node_timer(pos):start(meta:get_int("time")) + end + end + } + } + } +) diff --git a/scripts/doors.lua b/scripts/doors.lua new file mode 100644 index 0000000..2dfbdc8 --- /dev/null +++ b/scripts/doors.lua @@ -0,0 +1,322 @@ +local pgad_rules = { + {x = 1, y = 0, z = 0}, + {x = -1, y = 0, z = 0}, + {x = 0, y = 1, z = 0}, + {x = 0, y = -1, z = 0}, + {x = 0, y = 0, z = 1}, + {x = 0, y = 0, z = -1} +} +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:powerdoor1_1", + { + description = "Power door", + inventory_image = "portalgun_powerwall.png", + wield_image = "portalgun_powerwall.png", + groups = {mesecon = 1, unbreakable = 1, not_in_creative_inventory = 0}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + sounds = stone_sounds, + drawtype = "nodebox", + alpha = 160, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.4, 0.5, 0.5, 0.5} + }, + tiles = { + { + name = "portalgun_powerwall1.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.2 + } + } + }, + after_place_node = function(pos, placer, itemstack) + local name = placer:get_player_name() + minetest.get_meta(pos):set_string("owner", name) + local p2 = minetest.get_node(pos) + pos.y = pos.y + 1 + local n = minetest.get_node(pos) + if n.name == "air" then + minetest.set_node(pos, {name = "portalgun:powerdoor1_2", param2 = p2.param2}) + minetest.get_meta(pos):set_string("owner", name) + end + end, + on_punch = function(pos, node, player, pointed_thing) + local meta = minetest.get_meta(pos) + if meta:get_string("owner") == player:get_player_name() then + minetest.node_dig(pos, minetest.get_node(pos), player) + pos.y = pos.y + 1 + local un = minetest.get_node(pos).name + if un == "portalgun:powerdoor1_2" then + minetest.set_node(pos, {name = "air"}) + end + pos.y = pos.y - 1 + return true + end + end, + mesecons = { + conductor = { + state = mesecon.state.off, + onstate = "portalgun:powerdoor2_1", + rules = pgad_rules + } + } + } +) + +minetest.register_node( + "portalgun:powerdoor1_2", + { + description = "Power door", + inventory_image = "portalgun_powerwall.png", + groups = {mesecon = 1, unbreakable = 1, not_in_creative_inventory = 1}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + sounds = stone_sounds, + drawtype = "nodebox", + alpha = 160, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.4, 0.5, 0.5, 0.5} + }, + tiles = { + { + name = "portalgun_powerwall1.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 0.2 + } + } + }, + on_punch = function(pos, node, player, pointed_thing) + local meta = minetest.get_meta(pos) + if meta:get_string("owner") == player:get_player_name() then + minetest.set_node(pos, {name = "air"}) + pos.y = pos.y - 1 + local un = minetest.get_node(pos).name + if un == "portalgun:powerdoor1_1" then + minetest.node_dig(pos, minetest.get_node(pos), player) + end + pos.y = pos.y + 1 + return true + end + end, + mesecons = { + conductor = { + state = mesecon.state.off, + onstate = "portalgun:powerdoor2_2", + rules = pgad_rules + } + } + } +) + +minetest.register_node( + "portalgun:powerdoor2_1", + { + description = "Power door", + inventory_image = "portalgun_powerwall.png", + groups = {unbreakable = 1, mesecon = 1, not_in_creative_inventory = 1}, + paramtype = "light", + sunlight_propagates = true, + drawtype = "airlike", + walkable = false, + pointable = false, + diggable = false, + mesecons = { + conductor = { + state = mesecon.state.on, + offstate = "portalgun:powerdoor1_1", + rules = pgad_rules + } + } + } +) + +minetest.register_node( + "portalgun:powerdoor2_2", + { + description = "Power door", + inventory_image = "portalgun_powerwall.png", + groups = {unbreakable = 1, mesecon = 1, not_in_creative_inventory = 1}, + paramtype = "light", + sunlight_propagates = true, + drawtype = "airlike", + walkable = false, + pointable = false, + diggable = false, + mesecons = { + conductor = { + state = mesecon.state.on, + offstate = "portalgun:powerdoor1_2", + rules = pgad_rules + } + } + } +) +minetest.register_node( + "portalgun:door_1", + { + description = "Mesecon Door", + drop = "portalgun:door_1", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.125, 0.5, 0.5, 0.125} + } + }, + tiles = {"portalgun_testblock.png"}, + groups = {mesecon = 1, cracky = 1, level = 2, not_in_creative_inventory = 0}, + sounds = stone_sounds, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = false, + after_place_node = function(pos, placer, itemstack, pointed_thing) + local p = {x = pos.x, y = pos.y + 1, z = pos.z} + if minetest.registered_nodes[minetest.get_node(p).name].walkable then + return false + else + minetest.set_node(p, {name = "portalgun:door_2", param2 = minetest.get_node(pos).param2}) + end + end, + mesecons = { + effector = { + action_on = function(pos, node) + local p = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest.swap_node(p, {name = "portalgun:door_open_2", param2 = minetest.get_node(pos).param2}) + minetest.swap_node(pos, {name = "portalgun:door_open_1", param2 = minetest.get_node(pos).param2}) + minetest.sound_play("portalgun_door", {pos = pos, gain = 1, max_hear_distance = 5}) + end + } + }, + after_dig_node = function(pos, name, digger) + minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "air"}) + end + } +) + +minetest.register_node( + "portalgun:door_2", + { + description = "Door 2-1", + drawtype = "nodebox", + drop = "portalgun:door_1", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, -0.125, 0.5, 0.5, 0.125} + } + }, + tiles = {"portalgun_testblock.png"}, + groups = {mesecon = 1, cracky = 1, level = 2, not_in_creative_inventory = 1}, + sounds = wood_sounds, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = false, + mesecons = { + effector = { + action_on = function(pos, node) + local p = {x = pos.x, y = pos.y - 1, z = pos.z} + minetest.swap_node(p, {name = "portalgun:door_open_1", param2 = minetest.get_node(pos).param2}) + minetest.swap_node(pos, {name = "portalgun:door_open_2", param2 = minetest.get_node(pos).param2}) + minetest.sound_play("portalgun_door", {pos = pos, gain = 1, max_hear_distance = 5}) + end + } + }, + after_dig_node = function(pos, name, digger) + minetest.set_node({x = pos.x, y = pos.y - 1, z = pos.z}, {name = "air"}) + end + } +) + +minetest.register_node( + "portalgun:door_open_1", + { + description = "Door (open) 2-o-1", + drop = "portalgun:door_1", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {0.41, -0.5, -0.124, 1.41, 0.5, 0.125} + } + }, + tiles = {"portalgun_testblock.png"}, + groups = {mesecon = 1, cracky = 1, level = 2, not_in_creative_inventory = 1}, + sounds = wood_sounds, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = false, + after_dig_node = function(pos, name, digger) + minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, {name = "air"}) + end, + mesecons = { + effector = { + action_off = function(pos, node) + local p = {x = pos.x, y = pos.y + 1, z = pos.z} + minetest.sound_play("portalgun_door", {pos = pos, gain = 1, max_hear_distance = 5}) + minetest.swap_node(p, {name = "portalgun:door_2", param2 = minetest.get_node(pos).param2}) + minetest.swap_node(pos, {name = "portalgun:door_1", param2 = minetest.get_node(pos).param2}) + end + } + } + } +) + +minetest.register_node( + "portalgun:door_open_2", + { + description = "Door (open) 2-o-1", + drawtype = "nodebox", + drop = "portalgun:door_1", + node_box = { + type = "fixed", + fixed = { + {0.41, -0.5, -0.124, 1.41, 0.5, 0.125} + } + }, + tiles = {"portalgun_testblock.png"}, + groups = {mesecon = 1, cracky = 1, level = 2, not_in_creative_inventory = 1}, + sounds = wood_sounds, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + is_ground_content = false, + after_dig_node = function(pos, name, digger) + minetest.set_node({x = pos.x, y = pos.y - 1, z = pos.z}, {name = "air"}) + end, + mesecons = { + effector = { + action_off = function(pos, node) + local p = {x = pos.x, y = pos.y - 1, z = pos.z} + minetest.sound_play("portalgun_door", {pos = pos, gain = 1, max_hear_distance = 5}) + minetest.swap_node(p, {name = "portalgun:door_1", param2 = minetest.get_node(pos).param2}) + minetest.swap_node(pos, {name = "portalgun:door_2", param2 = minetest.get_node(pos).param2}) + end + } + } + } +) diff --git a/scripts/editingtools.lua b/scripts/editingtools.lua new file mode 100644 index 0000000..0a39568 --- /dev/null +++ b/scripts/editingtools.lua @@ -0,0 +1,64 @@ +minetest.register_tool( + "portalgun:pick", + { + --a pickaxe that can mine all blocks + description = "Portalgun Pickaxe", + inventory_image = "portalgun_pick.png", + tool_capabilities = { + full_punch_interval = 1.0, + max_drop_level = 3, + groupcaps = { + unbreakable = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3}, + fleshy = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3}, + choppy = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3}, + bendy = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3}, + cracky = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3}, + crumbly = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3}, + snappy = {times = {[1] = 1, [2] = 1, [3] = 1}, uses = 0, maxlevel = 3} + }, + damage_groups = {fleshy = 1000} + } + } +) +minetest.register_tool( + "portalgun:ed", + { + description = "Entity Destroyer", + inventory_image = "portalgun_edestroyer.png", + range = 15, + on_use = function(itemstack, user, pointed_thing) + local pos = user:get_pos() + if pointed_thing.type == "node" then + pos = pointed_thing.above + end + if pointed_thing.type == "object" then + pos = pointed_thing.ref:get_pos() + end + local name = user:get_player_name() + if minetest.check_player_privs(name, {kick = true}) == false then + minetest.chat_send_player(name, "You need the kick privilege to use this tool!") + return itemstack + end + for ii, ob in pairs(minetest.get_objects_inside_radius(pos, 7)) do + if ob:get_luaentity() then + ob:set_hp(0) + end + end + return itemstack + end + } +) +--register command for admins to build a testblock at the players position +minetest.register_chatcommand( + "testblock", + { + params = "", + description = "builds a testblock at the players position", + privs = {server = true}, + func = function(name, param) + local player = minetest.get_player_by_name(name) + local pos = player:get_pos() + minetest.set_node(pos, {name = "portalgun:testblock"}) + end + } +) diff --git a/scripts/fizzlers.lua b/scripts/fizzlers.lua new file mode 100644 index 0000000..bdd9b6d --- /dev/null +++ b/scripts/fizzlers.lua @@ -0,0 +1,88 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} + +minetest.register_node( + "portalgun:cplps1", + { + description = "Close player portal", + tiles = {"portalgun_gray.png"}, + groups = {mesecon = 2, snappy = 3, not_in_creative_inventory = 0}, + sounds = stone_sounds, + is_ground_content = false, + mesecons = { + effector = { + action_on = function(pos, node) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 6)) do + if ob and ob:is_player() then + portal_delete(ob:get_player_name(), 0) + end + end + minetest.swap_node(pos, {name = "portalgun:cplps2"}) + minetest.after( + (2), + function(pos) + minetest.swap_node(pos, {name = "portalgun:cplps1"}) + end, + pos + ) + + return false + end + } + } + } +) + +minetest.register_node( + "portalgun:cplps3", + { + description = "Close player portal when player is near", + tiles = {"portalgun_gray.png"}, + groups = {snappy = 3, not_in_creative_inventory = 0}, + sounds = stone_sounds, + is_ground_content = false, + --every 2 seconds, check if player is near and close portal if so + on_t = function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 4)) do + if ob and ob:is_player() then + minetest.sound_play("portalgun_close", {pos = pos, gain = 1.0, max_hear_distance = 10}) + portal_delete(ob:get_player_name(), 0) + end + --destroy all entities except players + if ob and not ob:is_player() then + ob:remove() + end + end + local timer = minetest.get_node_timer(pos) + timer:start(2) + return true + end, + after_place_node = function(pos, placer, itemstack, pointed_thing) + local timer = minetest.get_node_timer(pos) + timer:start(2) + end + } +) + +minetest.register_node( + "portalgun:cplps2", + { + description = "Close player portal", + tiles = {"portalgun_gray.png^[colorize:#ffe85977"}, + groups = {mesecon = 2, snappy = 3, not_in_creative_inventory = 1}, + sounds = stone_sounds, + is_ground_content = false, + paramtype = "light", + light_source = 4 + } +) diff --git a/scripts/gravityuse.lua b/scripts/gravityuse.lua new file mode 100644 index 0000000..18f6397 --- /dev/null +++ b/scripts/gravityuse.lua @@ -0,0 +1,173 @@ +portalgun_power = {} +portalgun_power_tmp_power = 0 + +function portalgun_gravity(itemstack, user, pointed_thing) + local ob = pointed_thing.ref + local at = ob:get_attach() + if at and at:get_luaentity() and at:get_luaentity().portalgun_power then + ob:set_detach() + local target = at:get_luaentity().target + if target and target:get_luaentity() and (target:get_luaentity().itemstring or target:get_luaentity().wsc) then + target:set_velocity({x = 0, y = -1, z = 0}) + target:set_acceleration({x = 0, y = -8, z = 0}) + end + return itemstack + end + if not ob:get_attach() and (ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().powerball ~= 1)) then + --if 4 blocks or closer to player + if vector.distance(ob:get_pos(), user:get_pos()) < 4 then + portalgun_power.user = user + portalgun_power.target = ob + if ob:is_player() then + portalgun_power.player = 1 + end + local m = minetest.add_entity(ob:get_pos(), "portalgun:power") + ob:set_attach(m, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + return itemstack + end + end + + return itemstack +end + +minetest.register_entity( + "portalgun:power", + { + hp_max = 100, + physical = false, + weight = 0, + collisionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2}, + visual = "sprite", + visual_size = {x = 1, y = 1}, + textures = {"portalgun_gravity.png"}, + spritediv = {x = 1, y = 1}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = 0, + timer = 0, + time = 0.1, + portalgun_power = 1, + portalgun = 1, + lifelime = 100, + on_activate = function(self, staticdata) + if portalgun_power.user then + self.user = portalgun_power.user + self.target = portalgun_power.target + self.player = portalgun_power.player + portalgun_power = {} + else + self.object:remove() + end + end, + on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) + if self.target and self.target:get_attach() then + self.target:set_detach() + self.target:set_hp(0) + end + end, + on_step = function(self, dtime) + self.timer = self.timer + dtime + if self.timer < self.time then + return self + end + self.timer = 0 + if self.target == nil or (not self.target:get_attach()) then + self.object:set_hp(0) + if self.sound then + minetest.sound_stop(self.sound) + end + end + if self.player then + self.lifelime = self.lifelime - 1 + if self.lifelime < 0 then + self.target:set_detach() + return self + end + end + local pos = self.user:get_pos() + if pos == nil then + return self + end + pos.y = pos.y + 1.6 + local dir = self.user:get_look_dir() + local npos = {x = pos.x + (dir.x * 2), y = pos.y + (dir.y * 2), z = pos.z + (dir.z * 2)} + if minetest.registered_nodes[minetest.get_node(npos).name].walkable then + return self + end + self.object:move_to(npos) + return self + end + } +) + +minetest.register_entity( + "portalgun:power2", + { + hp_max = 100, + physical = true, + weight = 10, + collisionbox = {-0.35, 0, -0.35, 0.35, 1, 0.35}, + visual = "sprite", + visual_size = {x = 1, y = 1}, + textures = {"portalgun_gravity.png"}, + spritediv = {x = 1, y = 1}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = 0, + timer = 0, + time = 0.025, + portalgun_power = 1, + portalgun = 1, + lifelime = 1000, + v = 0.3, + ltime = 0, + on_activate = function(self, staticdata) + if portalgun_power.user then + self.user = portalgun_power.user + self.target = portalgun_power.target + self.ltime = portalgun_power_tmp_power + portalgun_power = {} + else + self.object:remove() + end + end, + on_step = function(self, dtime) + local pos = self.object:get_pos() + local v = self.object:get_velocity() + local v2 = {x = v.x - self.v, y = (v.y - self.v) * 0.99, z = v.z - self.v} + + if v2.x < 0.5 and v2.x > -0.5 then + v2.x = 0 + end + if v2.y < 0.5 and v2.y > -0.5 then + v2.y = 0 + end + if v2.z < 0.5 and v2.z > -0.5 then + v2.z = 0 + end + + self.object:set_velocity(v2) + self.ltime = self.ltime - self.v + + if self.ltime < self.v or (v2.x + v2.y + v2.z == 0) then + self.lifelime = -1 + end + + local nexpos = {x = pos.x + (v.x * 0.05), y = pos.y + (v.y * 0.05) + 1, z = pos.z + (v.z * 0.05)} + if minetest.registered_nodes[minetest.get_node(nexpos).name].walkable then + self.lifelime = -1 + end + + self.lifelime = self.lifelime - 1 + if self.lifelime < 0 then + self.target:set_detach() + end + + if self.target == nil or (not self.target:get_attach()) then + self.object:set_hp(0) + return self + end + return self + end + } +) diff --git a/scripts/objectdestroyer.lua b/scripts/objectdestroyer.lua new file mode 100644 index 0000000..87a26e2 --- /dev/null +++ b/scripts/objectdestroyer.lua @@ -0,0 +1,51 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:objdestroyer_1", + { + description = "Object destroyer (destroys on active)", + tiles = {"portalgun_testblock.png^[colorize:#FF0000aa"}, + groups = {cracky = 2, mesecon = 1}, + sounds = stone_sounds, + mesecons = { + effector = { + action_on = function(pos, node) + minetest.set_node(pos, {name = "portalgun:objdestroyer_2"}) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 5)) do + if ob:get_luaentity() then + ob:set_hp(0) + end + end + end + } + } + } +) +minetest.register_node( + "portalgun:objdestroyer_2", + { + description = "Obj destroyer", + tiles = {"portalgun_testblock.png^[colorize:#FF0000cc"}, + groups = {cracky = 2, mesecon = 1, not_in_creative_inventory = 1}, + sunlight_propagates = true, + drop = "portalgun:objdestroyer_1", + paramtype = "light", + light_source = 14, + mesecons = { + conductor = { + state = mesecon.state.on, + offstate = "portalgun:objdestroyer_1" + } + } + } +) diff --git a/scripts/portalgun.lua b/scripts/portalgun.lua new file mode 100644 index 0000000..894c050 --- /dev/null +++ b/scripts/portalgun.lua @@ -0,0 +1,664 @@ +portalgun_portal = {} +portalgun_portal_tmp_user_abort = 0 +portalgun_portal_tmp_user = "" +local portalgun_timer = 1.2 +local portalgun_time = 0 +portalgun_lifelime = 1200 --deletes portals that not used after a while +portalgun_max_rage = 100 +portalgun_max_use_per_secund_time = 4 --destroys the portal if excessive used +portalgun_max_use_per_secund = 25 --4 & 25 is default = teleported (teleported 25 times in 4 sec) +function portalgun_param2(pos, param2, r) + local pos2 = {x = pos.x, y = pos.y, z = pos.z} + if r then + if param2 == 0 then + pos2.x = pos2.x - 1 + elseif param2 == 1 then + pos2.z = pos2.z + 1 + elseif param2 == 2 then + pos2.x = pos2.x + 1 + elseif param2 == 3 then + pos2.z = pos2.z - 1 + end + else + if param2 == 0 then + pos2.x = pos2.x + 1 + elseif param2 == 1 then + pos2.z = pos2.z - 1 + elseif param2 == 2 then + pos2.x = pos2.x - 1 + elseif param2 == 3 then + pos2.z = pos2.z + 1 + end + end + return pos2 +end + +local function portalgun_getLength(a) -- get length of an array / table + local count = 0 + for _ in pairs(a) do + count = count + 1 + end + return count +end + +function portal_delete(name, n) -- using set_hp & :punch instand of :remove ... no risk for crash if something attach it + if portalgun_portal[name] == nil then + return + end + if (n == 1 or n == 0) and portalgun_portal[name].portal1 ~= nil then + if n == 0 then + local pos = portalgun_portal[name].portal1:get_pos() + if pos ~= nil then + minetest.sound_play("portalgun_closeportals", {pos = pos, max_hear_distance = 20, gain = 1}) + end + end + portalgun_portal[name].portal1_active = false + portalgun_portal[name].portal1:set_hp(0) + end + if (n == 2 or n == 0) and portalgun_portal[name].portal2 ~= nil then + if n == 0 then + local pos = portalgun_portal[name].portal2:get_pos() + if pos ~= nil then + minetest.sound_play("portalgun_closeportals", {pos = pos, max_hear_distance = 20, gain = 1}) + end + end + portalgun_portal[name].portal2_active = false + portalgun_portal[name].portal2:set_hp(0) + end + if n == 0 then + portalgun_portal[name] = nil + end +end + +minetest.register_on_leaveplayer( + function(player) -- deletes user the profile (saveing memory) + local name = player:get_player_name() + portal_delete(name, 0) + portalgun_portal[name] = nil + end +) +minetest.register_on_dieplayer( + function(player) + local name = player:get_player_name() + portal_delete(name, 0) + portalgun_portal[name] = nil + end +) + +portalgun_on_step = function(self, dtime) + local name = self.user + + if portalgun_portal[self.user] == nil then + self.object:remove() + return self + end + + if + (self.project == 1 and self.use ~= portalgun_portal[self.user].portal1_use) or + (self.project == 2 and self.use ~= portalgun_portal[self.user].portal2_use) + then + self.object:remove() + return self + end + + if portalgun_portal[name].lifelime < 0 then + portal_delete(name, 0) + return self + end + + if portalgun_portal[name].portal1_active and portalgun_portal[name].portal2_active then -- makes lifetime equal when both is acive, or it will be half + portalgun_portal[name].lifelime = portalgun_portal[name].lifelime - 0.5 + else + portalgun_portal[name].lifelime = portalgun_portal[name].lifelime - 1 + return self -- abort when only 1 is active (saves cpu) + end + + if portalgun_portal[name].timer > 0 then -- makes teleported stuff wont move back at same time (bug fix) + portalgun_portal[name].timer = portalgun_portal[name].timer - dtime + return self + end + + if self.portal_max_use > 0 then -- makes teleported stuff wont move back at same time (bug fix) + self.portal_max_use_time = self.portal_max_use_time + dtime + if self.portal_max_use >= portalgun_max_use_per_secund then + portal_delete(name, self.project) + return self + elseif self.portal_max_use_time >= portalgun_max_use_per_secund_time then + self.portal_max_use_time = 0 + self.portal_max_use = 0 + end + end + + local pos1 = 0 + local pos2 = 0 + local d1 = 0 + local d2 = 0 + if self.project == 1 then + pos1 = portalgun_portal[name].portal1_pos + pos2 = portalgun_portal[name].portal2_pos + d1 = portalgun_portal[name].portal1_dir + d2 = portalgun_portal[name].portal2_dir + else + pos1 = portalgun_portal[name].portal2_pos + pos2 = portalgun_portal[name].portal1_pos + d1 = portalgun_portal[name].portal2_dir + d2 = portalgun_portal[name].portal1_dir + end + + -- portalgun_front_of_field should fix teleport through walls, but is not working in all directions + -- waiting with this issue + + if pos2 ~= 0 and pos1 ~= 0 then + for ii, ob in pairs(minetest.get_objects_inside_radius(pos1, self.area)) do + if pos2 ~= 0 then --and portalgun_front_of_field(self.object,ob) + if + (ob:is_player()) or + (ob:get_luaentity() and ob:get_luaentity().portalgun ~= 1 and + ob:get_luaentity().name:find(":text", 4) == nil) + then + if ob:get_attach() then + ob:set_detach() + ob:set_acceleration({x = 0, y = -10, z = 0}) + end + --set velocity then teleport + local p = pos2 + local x = 0 + local y = 0 + local z = 0 + local dis = 2 + if p == nil or p.x == nil then + return self + end + + if ob:is_player() then + local v = ob:get_player_velocity() + local player_name = ob:get_player_name() + portalgun_power.user = player_name + portalgun_power.target = ob + local vv = {x = v.x, y = v.y, z = v.z} + -- get the highest velocity + dis = 2 + if vv.x + vv.y + vv.z <= 0.3 then + if self.small == true then + vv.x = 1.4 + else + vv.x = 2 + end + end + if vv.x + vv.y + vv.z == 0 then + vv.x = 2 + end + if vv.x < 0 then + vv.x = vv.x * -1 + end + if vv.y < 0 then + vv.y = vv.y * -1 + end + if vv.z < 0 then + vv.z = vv.z * -1 + end + if vv.x > vv.z then + vv.a = vv.x + else + vv.a = vv.z + end + if vv.a < vv.y then + vv.a = vv.y + end + portalgun_power_tmp_power = vv.a + local m = minetest.add_entity(ob:get_pos(), "portalgun:power2") + ob:set_attach(m, "", {x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + m:set_velocity(v) + m:set_acceleration({x = 0, y = -10, z = 0}) + ob = m + end + + if ob:is_player() == false then + local v = ob:get_velocity() + if v.x < 0 then + v.x = v.x * -1 + end + if v.y < 0 then + v.y = v.y * -1 + end + if v.z < 0 then + v.z = v.z * -1 + end + + local vv = 0 -- get the highest velocity + if v.x > v.z then + vv = v.x + else + vv = v.z + end + if vv < v.y then + vv = v.y + end + v.x = 0 + v.y = 0 + v.z = 0 + if d2 == "x+" then + v.x = vv + end + if d2 == "x-" then + v.x = vv * -1 + end + if d2 == "y+" then + v.y = vv + end + if d2 == "y-" then + v.y = vv * -1 + end + if d2 == "z+" then + v.z = vv + end + if d2 == "z-" then + v.z = vv * -1 + end + ob:set_velocity({x = v.x, y = v.y, z = v.z}) + end + if d2 == "x+" then + x = 2 + elseif d2 == "x-" then + x = -dis + elseif d2 == "y+" then + y = dis + elseif d2 == "y-" then + y = -dis + elseif d2 == "z+" then + z = dis + elseif d2 == "z-" then + z = -dis + end + local obpos = {x = p.x + x, y = p.y + y, z = p.z + z} + portalgun_portal[name].timer = 0.2 + self.portal_max_use = self.portal_max_use + 1 + ob:set_pos(obpos, false) + portalgun_portal[name].lifelime = portalgun_lifelime + minetest.sound_play( + "portalgun_teleport", + {pos = portalgun_portal[name].portal1_pos, max_hear_distance = 10, gain = 30} + ) + minetest.sound_play( + "portalgun_teleport", + {pos = portalgun_portal[name].portal2_pos, max_hear_distance = 10, gain = 30} + ) + end --end of set velocity part then teleport + end + end + end +end + +minetest.register_entity( + "portalgun:portal", + { + -- the portals + hp_max = 10000, + visual = "mesh", + mesh = "portalgun_portal_xp.obj", + physical = false, + textures = {"portalgun_blue.png"}, + visual_size = {x = 1, y = 1}, + spritediv = {x = 7, y = 0}, + collisionbox = {0, 0, 0, 0, 0, 0}, + timer = 0, + user = "", + project = 1, + portalgun = 1, + portal_max_use = 0, + portal_max_use_time = 0, + area = 2, + small = false, + get_staticdata = function(self) + return minetest.serialize( + { + user = self.user, + project = self.project, + use = self.use + } + ) + end, + on_activate = function(self, staticdata) + local data = minetest.deserialize(staticdata) + if data and type(data) == "table" then + self.user = data.user + self.project = data.project + self.use = data.use + if portalgun_portal[self.user] == nil then + self.object:remove() + return self + end + if + (self.project == 1 and self.use ~= portalgun_portal[self.user].portal1_use) or + (self.project == 2 and self.use ~= portalgun_portal[self.user].portal2_use) + then + self.object:remove() + return self + end + elseif portalgun_portal_tmp_user ~= "" then + self.user = portalgun_portal_tmp_user + portalgun_portal_tmp_user = "" + self.project = portalgun_portal[self.user].project + + if self.project == 1 then -- if inactivated then activated and another portal is created: remove + self.use = portalgun_portal[self.user].portal1_use + else + self.use = portalgun_portal[self.user].portal2_use + end + else + self.object:remove() + return self + end + + if portalgun_portal[self.user] == nil then + self.object:remove() + return self + end + + local d = "" + if self.project == 1 then + d = portalgun_portal[self.user].portal1_dir + self.object:set_properties({textures = {"portalgun_blue.png"}}) + else + d = portalgun_portal[self.user].portal2_dir + self.object:set_properties({textures = {"portalgun_orange.png"}}) + end + if d == "x+" then + self.object:set_yaw(math.pi * 0) + elseif d == "x-" then + self.object:set_yaw(math.pi * 1) + elseif d == "y+" then + self.object:set_properties({mesh = "portalgun_portal_yp.obj"}) -- becaouse there is no "setpitch" + elseif d == "y-" then + self.object:set_properties({mesh = "portalgun_portal_ym.obj"}) -- becaouse there is no "setpitch" + elseif d == "z+" then + self.object:set_yaw(math.pi * 0.5) + elseif d == "z-" then + self.object:set_yaw(math.pi * 1.5) + end + if d == "y+" then + local pos1 = {} + if self.project == 1 then + pos1 = portalgun_portal[self.user].portal1_pos + else + pos1 = portalgun_portal[self.user].portal2_pos + end + if portalgun_portal[self.user].y > 8 then + pos1.y = pos1.y + 1 + end + if portalgun_portal[self.user].y > 12 then + pos1.y = pos1.y + 1 + end + if self.project == 1 then + portalgun_portal[self.user].portal1_pos = pos1 + else + portalgun_portal[self.user].portal2_pos = pos1 + end + elseif + string.find(d, "y", 1) == nil and (portalgun_portal[self.user].x + portalgun_portal[self.user].z < 2.5) + then + self.area = 1.2 + self.small = true + self.object:set_properties({visual_size = {x = 0.7, y = 0.7}}) + end + end, + on_step = portalgun_on_step + } +) +minetest.register_craftitem( + ":", + { + description = "Portalgun", + range = 100, + inventory_image = "portalgun_gun0_rndr.png", + wield_image = "portalgun_gun0_rndr.png", + tool_capabilities = { + full_punch_interval = 0.5, + max_drop_level = 3, + damage_groups = {fleshy = 1} + }, + on_place = function(itemstack, user, pointed_thing) + local node = minetest.get_node(pointed_thing.under) + if node.name == "portalgun:button" then + --use the item normally + minetest.item_place(itemstack, user, pointed_thing) + else + portalgun_onuse(itemstack, user, pointed_thing, 2) + end + return itemstack + end, + on_use = function(itemstack, user, pointed_thing) + --if pointing at turret then start breaking it + if pointed_thing.type == "node" then + local node = minetest.get_node(pointed_thing.under) + if node.name == "portalgun:turretgun" or node.name == "portalgun:turretgun2" then + minetest.remove_node(pointed_thing.under) + end + end + portalgun_onuse(itemstack, user, pointed_thing, 1) + return itemstack + end + } +) + +local function rnd(r) + return math.floor(r + 0.5) +end + +function portalgun_onuse(itemstack, user, pointed_thing, mode) -- using the gun + if pointed_thing.type == "object" then + portalgun_gravity(itemstack, user, pointed_thing) + return itemstack + end + + local pos = user:get_pos() + local dir = user:get_look_dir() + local key = user:get_player_control() + local name = user:get_player_name() + local exist = 0 + + local item = itemstack:to_table() + local ob = {} + ob.project = 1 + ob.lifelime = portalgun_lifelime + ob.portal1 = 0 + ob.portal2 = 0 + ob.portal1_dir = 0 + ob.portal2_dir = 0 + ob.portal2_pos = 0 + ob.portal1_pos = 0 + ob.user = user:get_player_name() + + if portalgun_portal[name] == nil then -- new portal profile + portalgun_portal[name] = { + lifelime = portalgun_lifelime, + project = 1, + timer = 0, + portal1_active = false, + portal2_active = false, + portal1_use = 0, + portal2_use = 0 + } + end + + if key.sneak then + portal_delete(name, 0) + return itemstack + end + + pos.y = pos.y + 1.5 + + -- the project + + for i = 1, portalgun_max_rage, 0.5 do + local nname = + minetest.get_node({x = pos.x + (dir.x * i), y = pos.y + (dir.y * i), z = pos.z + (dir.z * i)}).name + if minetest.registered_nodes[nname].walkable then + portalgun_portal[name].lifelime = portalgun_lifelime + + if minetest.get_node_group(nname, "antiportal") > 0 then + minetest.sound_play("portalgun_error", {pos = pos, max_hear_distance = 5, gain = 3}) + return itemstack + elseif minetest.get_node_group(nname, "proportal") == 0 then + minetest.sound_play("portalgun_error", {pos = pos, max_hear_distance = 5, gain = 3}) + return itemstack + end + + if + minetest.registered_nodes[ + minetest.get_node( + {x = rnd(pos.x + (dir.x * i)), y = rnd(pos.y + (dir.y * i) + 1), z = rnd(pos.z + (dir.z * i))} + ).name + ].walkable == false and rnd(user:get_pos().y) > rnd(pos.y + (dir.y * i)) + then + portalgun_setportal(pos, name, dir, i, mode, "y+") + return itemstack + elseif + minetest.registered_nodes[ + minetest.get_node( + {x = rnd(pos.x + (dir.x * i)), y = rnd(pos.y + (dir.y * i) - 1), z = rnd(pos.z + (dir.z * i))} + ).name + ].walkable == false and rnd(user:get_pos().y) < rnd(pos.y + (dir.y * i)) + then + portalgun_setportal(pos, name, dir, i, mode, "y-") + return itemstack + elseif + minetest.registered_nodes[ + minetest.get_node( + {x = rnd(pos.x + (dir.x * i) - 1), y = rnd(pos.y + (dir.y * i)), z = rnd(pos.z + (dir.z * i))} + ).name + ].walkable == false and rnd(user:get_pos().x) < rnd(pos.x + (dir.x * i)) + then + portalgun_setportal(pos, name, dir, i, mode, "x-") + return itemstack + elseif + minetest.registered_nodes[ + minetest.get_node( + {x = rnd(pos.x + (dir.x * i)) + 1, y = rnd(pos.y + (dir.y * i)), z = rnd(pos.z + (dir.z * i))} + ).name + ].walkable == false and rnd(user:get_pos().x) > rnd(pos.x + (dir.x * i)) + then + portalgun_setportal(pos, name, dir, i, mode, "x+") + return itemstack + elseif + minetest.registered_nodes[ + minetest.get_node( + {x = rnd(pos.x + (dir.x * i)), y = rnd(pos.y + (dir.y * i)), z = rnd(pos.z + (dir.z * i) - 1)} + ).name + ].walkable == false and rnd(user:get_pos().z) < rnd(pos.z + (dir.z * i)) + then + portalgun_setportal(pos, name, dir, i, mode, "z-") + return itemstack + elseif + minetest.registered_nodes[ + minetest.get_node( + {x = rnd(pos.x + (dir.x * i)), y = rnd(pos.y + (dir.y * i)), z = rnd(pos.z + (dir.z * i) + 1)} + ).name + ].walkable == false and rnd(user:get_pos().z) > rnd(pos.z + (dir.z * i)) + then + portalgun_setportal(pos, name, dir, i, mode, "z+") + return itemstack + end + minetest.sound_play("portalgun_error", {pos = pos, max_hear_distance = 20, gain = 3}) + return itemstack + end + end + return itemstack +end + +function portalgun_setportal(pos, name, dir, i, mode, portal_dir) + local lpos = {x = pos.x + (dir.x * (i - 1)), y = pos.y + (dir.y * (i - 1)), z = pos.z + (dir.z * (i - 1))} -- last pos + local cpos = {x = pos.x + (dir.x * i), y = pos.y + (dir.y * i), z = pos.z + (dir.z * i)} -- corrent poss + if portal_dir == "y+" then + cpos.y = (math.floor(cpos.y + 0.5)) + 0.524 + elseif portal_dir == "y-" then + cpos.y = (math.floor(cpos.y + 0.5)) - 0.524 + elseif portal_dir == "z+" then + cpos.z = (math.floor(cpos.z + 0.5)) + 0.524 + elseif portal_dir == "z-" then + cpos.z = (math.floor(cpos.z + 0.5)) - 0.524 + elseif portal_dir == "x+" then + cpos.x = (math.floor(cpos.x + 0.5)) + 0.524 + elseif portal_dir == "x-" then + cpos.x = (math.floor(cpos.x + 0.5)) - 0.524 + end + + if portal_dir == "x+" or portal_dir == "x-" then -- auto correct (place in center) + cpos.y = (math.floor(cpos.y + 0.5)) + cpos.z = (math.floor(cpos.z + 0.5)) + elseif portal_dir == "y+" or portal_dir == "y-" then + cpos.x = (math.floor(cpos.x + 0.5)) + cpos.z = (math.floor(cpos.z + 0.5)) + elseif portal_dir == "z+" or portal_dir == "z-" then + cpos.x = (math.floor(cpos.x + 0.5)) + cpos.y = (math.floor(cpos.y + 0.5)) + end + + if minetest.registered_nodes[minetest.get_node(cpos).name].walkable then + minetest.sound_play("portalgun_error", {pos = pos, max_hear_distance = 5, gain = 3}) + return false + end + + if string.find(portal_dir, "x", 1) or string.find(portal_dir, "z", 1) then -- auto correct (move from bottom / top) + local testpos1 = {x = cpos.x, y = cpos.y - 1, z = cpos.z} + local testpos2 = {x = cpos.x, y = cpos.y + 1, z = cpos.z} + if + minetest.registered_nodes[minetest.get_node(testpos1).name].walkable and + minetest.registered_nodes[minetest.get_node(testpos2).name].walkable == false + then + cpos.y = cpos.y + 0.5 + elseif + minetest.registered_nodes[minetest.get_node(testpos2).name].walkable and + minetest.registered_nodes[minetest.get_node(testpos1).name].walkable == false + then + cpos.y = cpos.y - 0.5 + end + end + + portalgun_portal_tmp_user = name + portalgun_portal[name].x = pos.x - lpos.x + portalgun_portal[name].y = pos.y - lpos.y + portalgun_portal[name].z = pos.z - lpos.z + portalgun_portal[name].project = mode + + if portalgun_portal[name].x < 0 then + portalgun_portal[name].x = portalgun_portal[name].x * -1 + end + if portalgun_portal[name].z < 0 then + portalgun_portal[name].z = portalgun_portal[name].z * -1 + end + + if mode == 1 then + portal_delete(name, 1) + portalgun_portal[name].portal1_use = portalgun_portal[name].portal1_use + 1 + portalgun_portal[name].portal1_dir = portal_dir + portalgun_portal[name].portal1_pos = cpos + portalgun_portal[name].portal1 = minetest.add_entity(cpos, "portalgun:portal") + portalgun_portal[name].portal1_active = true + minetest.sound_play("portalgun_portalblue", {pos = cpos, max_hear_distance = 20, gain = 1}) + else + portal_delete(name, 2) + portalgun_portal[name].portal2_use = portalgun_portal[name].portal2_use + 1 + portalgun_portal[name].portal2_dir = portal_dir + portalgun_portal[name].portal2_pos = cpos + portalgun_portal[name].portal2 = minetest.add_entity(cpos, "portalgun:portal") + portalgun_portal[name].portal2_active = true + minetest.sound_play("portalgun_portalorange", {pos = cpos, max_hear_distance = 20, gain = 1}) + end +end + +portalgun_front_of_field = function(ob, ob2) + local pos2 = ob2:get_pos() + return vector.distance(ob:get_pos(), pos2) > vector.distance(portalgun_pointat(ob), pos2) +end + +portalgun_pointat = function(ob) + local pos = ob:get_pos() + local yaw = ob:get_yaw() + if yaw ~= yaw or type(yaw) ~= "number" then + yaw = 0 + end + local z = math.sin(yaw) * -0.1 + local x = math.cos(yaw) * 0.1 + return {x = pos.x + x, y = pos.y, z = pos.z + z} +end diff --git a/scripts/portaltarget.lua b/scripts/portaltarget.lua new file mode 100644 index 0000000..2787981 --- /dev/null +++ b/scripts/portaltarget.lua @@ -0,0 +1,52 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +local portaltarget_sig = { + {1, "portalgun_blue.png"}, + {2, "portalgun_orange.png"} +} + +for ii = 1, #portaltarget_sig, 1 do + minetest.register_node( + "portalgun:portaltarget_" .. portaltarget_sig[ii][1], + { + description = "Portal target " .. portaltarget_sig[ii][1], + tiles = {"portalgun_testblock.png^" .. portaltarget_sig[ii][2]}, + groups = {mesecon = 2, cracky = 2}, + mesecons = {receptor = {state = "off"}}, + sounds = stone_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + on_timer = function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + if + ob:get_luaentity() and ob:get_luaentity().portalgun and + ob:get_luaentity().project == portaltarget_sig[ii][1] + then + mesecon.receptor_on(pos) + + return true + end + end + mesecon.receptor_off(pos) + return true + end, + on_construct = function(pos) + if not mesecon then + return false + end + minetest.get_node_timer(pos):start(2) + end + } + ) +end diff --git a/scripts/powerball.lua b/scripts/powerball.lua new file mode 100644 index 0000000..1b36de5 --- /dev/null +++ b/scripts/powerball.lua @@ -0,0 +1,86 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +new = 0 +minetest.register_entity( + "portalgun:powerball", + { + hp_max = 1000, + physical = true, + weight = 0, + collisionbox = {-0.4, -0.4, -0.4, 0.4, 0.4, 0.4}, + visual = "sprite", + visual_size = {x = 1.1, y = 1.1}, + textures = {"portalgun_powrball.png"}, + initial_sprite_basepos = {x = 0, y = 0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = 0, + portalgun = 2, + powerball = 1, + on_activate = function(self, staticdata) + if new == 0 then + self.object:remove() + return self + end + new = 0 + local pos = self.object:get_pos() + self.sound = minetest.sound_play("portalgun_powerball", {pos = pos, max_hear_distance = 10, gain = 0.5}) + minetest.sound_play("portalgun_powerballbonce", {pos = pos, max_hear_distance = 10, gain = 1}) + end, + on_step = function(self, dtime) + self.timer = self.timer + dtime + if self.timer < 0.2 then + return self + end + self.timer = 0 + local pos = self.object:get_pos() + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + if + ob:is_player() or + (ob:get_luaentity() and ob:get_luaentity().portalgun ~= 1 and ob:get_luaentity().wsc == nil and + ob:get_luaentity().powerball ~= 1) + then + ob:set_hp(0) + end + end + self.timer2 = self.timer2 + 1 + self.timer3 = self.timer3 + 1 + if self.timer3 >= 9 then + self.timer3 = 0 + minetest.sound_stop(self.sound) + self.sound = minetest.sound_play("portalgun_powerball", {pos = pos, max_hear_distance = 10, gain = 0.5}) + end + if self.timer2 > 40 then + minetest.sound_stop(self.sound) + self.object:set_hp(0) + return self + end + local v = self.object:get_velocity() + local nextn = {x = pos.x + (v.x) / 3, y = pos.y + (v.y) / 3, z = pos.z + (v.z) / 3} + local nname = minetest.get_node(nextn).name + if minetest.registered_nodes[nname].walkable then + if nname == "portalgun:powerballtarget" and mesecon then + mesecon.receptor_on(nextn) + minetest.get_node_timer(nextn):start(5) + self.object:remove() + end + self.object:set_velocity({x = v.x * -1, y = v.y * -1, z = v.z * -1}) + minetest.sound_play("portalgun_powerballbonce", {pos = pos, max_hear_distance = 10, gain = 1}) + end + end, + timer = 0, + timer2 = 0, + timer3 = 0, + sound = {} + } +) diff --git a/scripts/powerballspawner.lua b/scripts/powerballspawner.lua new file mode 100644 index 0000000..7008591 --- /dev/null +++ b/scripts/powerballspawner.lua @@ -0,0 +1,95 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +new = 0 +minetest.register_node( + "portalgun:powerballspawner", + { + description = "Power ball spawner", + tiles = {"steel.png", "steel.png", "steel.png", "steel.png", "steel.png", "portalgun_powerballspawner.png"}, + groups = {cracky = 2}, + sounds = glass_sounds, + is_ground_content = false, + paramtype2 = "facedir", + on_construct = function(pos) + minetest.get_node_timer(pos):start(10) + end, + on_timer = function(pos, elapsed) + local dir = minetest.get_node(pos).param2 + local v = {x = 0, y = 0, z = 0} + if dir == 0 then + v.z = -1 + elseif dir == 1 then + v.x = -1 + elseif dir == 2 then + v.z = 1 + elseif dir == 3 then + v.x = 1 + elseif dir == 5 then + v.y = -1 + elseif dir == 4 then + v.y = 1 + else + v.y = -1 + end + local pv = {x = pos.x + v.x, y = pos.y + v.y, z = pos.z + v.z} + new = 1 + local m = minetest.add_entity(pv, "portalgun:powerball") + m:set_velocity({x = v.x * 4, y = v.y * 4, z = v.z * 4}) + return true + end + } +) +minetest.register_node( + "portalgun:powerballspawner2", + { + description = "Power ball spawner (spawn on activate)", + tiles = { + "steel.png", + "steel.png", + "steel.png", + "steel.png", + "steel.png", + "portalgun_powerballspawner.png^[colorize:#aaaa0055" + }, + groups = {cracky = 2, mesecon = 1}, + sounds = glass_sounds, + is_ground_content = false, + paramtype2 = "facedir", + on_place = minetest.rotate_node, + mesecons = { + effector = { + action_on = function(pos, node) + local dir = minetest.get_node(pos).param2 + local v = {x = 0, y = 0, z = 0} + if dir == 0 then + v.z = -1 + elseif dir == 1 then + v.x = -1 + elseif dir == 2 then + v.z = 1 + elseif dir == 3 then + v.x = 1 + elseif dir == 8 then + v.y = -1 + elseif dir == 4 then + v.y = 1 + end + local pv = {x = pos.x + v.x, y = pos.y + v.y, z = pos.z + v.z} + new = 1 + local m = minetest.add_entity(pv, "portalgun:powerball") + m:set_velocity({x = v.x * 4, y = v.y * 4, z = v.z * 4}) + end + } + } + } +) diff --git a/scripts/powerballtarget.lua b/scripts/powerballtarget.lua new file mode 100644 index 0000000..ac8fdfc --- /dev/null +++ b/scripts/powerballtarget.lua @@ -0,0 +1,27 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:powerballtarget", + { + description = "Power ball target", + tiles = {"portalgun_powerballstarget.png"}, + groups = {mesecon = 2, cracky = 2}, + mesecons = {receptor = {state = "off"}}, + sounds = stone_sounds, + is_ground_content = false, + on_timer = function(pos, elapsed) + mesecon.receptor_off(pos) + return false + end + } +) diff --git a/scripts/pressureplatforms.lua b/scripts/pressureplatforms.lua new file mode 100644 index 0000000..af179d3 --- /dev/null +++ b/scripts/pressureplatforms.lua @@ -0,0 +1,236 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +local ptgwsc = { + {"weightedstoragecube.png", "portalgun_presplat.png", "(blue)"}, + {"weightedstoragecube2.png", "portalgun_presplat2.png", "(orange)"}, + {"weightedstoragecube3.png", "portalgun_presplat3.png", "(yellow)"}, + {"weightedstoragecube4.png", "portalgun_presplat4.png", "(green)"}, + {"weightedcompanioncube.png", "portalgun_presplat.png", "(blue companion)"}, + {"weightedcompanioncube2.png", "portalgun_presplat2.png", "(orange companion)"}, + {"weightedcompanioncube3.png", "portalgun_presplat3.png", "(yellow companion)"}, + {"weightedcompanioncube4.png", "portalgun_presplat4.png", "(green companion)"} +} + +for ii = 1, #ptgwsc, 1 do + minetest.register_node( + "portalgun:plantform1_" .. ii, + { + description = "Pressure platform " .. ptgwsc[ii][3], + tiles = {ptgwsc[ii][2], "cloud.png", "cloud.png", "cloud.png", "cloud.png", "cloud.png"}, + groups = {mesecon = 2, cracky = 1, not_in_creative_inventory = 0}, + mesecons = {receptor = {state = "off"}}, + paramtype = "light", + sunlight_propagates = true, + sounds = stone_sounds, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, + {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, + {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, + {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, + {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, + {-0.5, -0.5, -0.5, 0.5, -0.3125, 0.5} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(2) + end, + on_timer = function(pos, elapsed) + if not mesecon then + return false + end + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if ob:get_luaentity() and ob:get_luaentity().wsc == ii then + local node = minetest.get_node(pos) + mesecon.receptor_on(pos) + minetest.set_node( + pos, + {name = "portalgun:plantform2_" .. ii, param1 = node.param1, param2 = node.param2} + ) + end + return true + end + return true + end + } + ) + + minetest.register_node( + "portalgun:plantform2_" .. ii, + { + description = "Pressure platform", + tiles = {ptgwsc[ii][2], "cloud.png", "cloud.png", "cloud.png", "cloud.png", "cloud.png"}, + drop = "portalgun:plantform1_" .. ii, + groups = {mesecon = 2, cracky = 1, not_in_creative_inventory = 1}, + mesecons = {receptor = {state = "on"}}, + paramtype = "light", + sunlight_propagates = true, + light_source = 14, + sounds = stone_sounds, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, + {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, + {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, + {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, + {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(2) + end, + on_timer = function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if ob:get_luaentity() and ob:get_luaentity().wsc == ii then + return true + end + end + mesecon.receptor_off(pos) + local node = minetest.get_node(pos) + minetest.set_node( + pos, + {name = "portalgun:plantform1_" .. ii, param1 = node.param1, param2 = node.param2} + ) + return true + end + } + ) +end -- of for # + +minetest.register_node( + "portalgun:plantform_nu1", + { + description = "Pressure platform (player or cube)", + tiles = {"portalgun_presplat5.png", "cloud.png", "cloud.png", "cloud.png", "cloud.png", "cloud.png"}, + groups = {mesecon = 2, cracky = 1, not_in_creative_inventory = 0}, + mesecons = {receptor = {state = "off"}}, + paramtype = "light", + sunlight_propagates = true, + sounds = stone_sounds, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, + {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, + {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, + {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, + {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, + {-0.5, -0.5, -0.5, 0.5, -0.3125, 0.5} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(2) + end, + on_timer = function(pos, elapsed) + if not mesecon then + return false + end + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().wsc) then + local node = minetest.get_node(pos) + mesecon.receptor_on(pos) + minetest.set_node( + pos, + {name = "portalgun:plantform_nu2", param1 = node.param1, param2 = node.param2} + ) + end + return true + end + return true + end + } +) +minetest.register_node( + "portalgun:plantform_nu2", + { + description = "Pressure platform", + tiles = {"portalgun_presplat5.png", "cloud.png", "cloud.png", "cloud.png", "cloud.png", "cloud.png"}, + drop = "portalgun:plantform_nu1", + groups = {mesecon = 2, cracky = 1, not_in_creative_inventory = 1}, + mesecons = {receptor = {state = "on"}}, + paramtype = "light", + sunlight_propagates = true, + light_source = 14, + sounds = stone_sounds, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, + {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, + {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, + {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, + {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(2) + end, + on_timer = function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do + if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().wsc) then + return true + end + end + mesecon.receptor_off(pos) + local node = minetest.get_node(pos) + minetest.set_node(pos, {name = "portalgun:plantform_nu1", param1 = node.param1, param2 = node.param2}) + return true + end + } +) +minetest.register_node( + "portalgun:planthole", + { + description = "Plathole (activate by any cube, 2 blocks under)", + tiles = {"cloud.png"}, + groups = {mesecon = 2, cracky = 1}, + mesecons = {receptor = {state = "off"}}, + paramtype = "light", + sunlight_propagates = true, + sounds = stone_sounds, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-1.5, -0.5, -1.5, 0.5, -0.25, -1.3}, + {-1.5, -0.5, 0.3, 0.5, -0.25, 0.5}, + {0.3, -0.5, -1.5, 0.5, -0.25, 0.5}, + {-1.5, -0.5, -1.5, -1.3, -0.25, 0.5}, + {0.5, -0.5, -0.9, 0.7, -0.375, -0.0625}, + {-1.7, -0.5, -0.9, -1.5, -0.3125, -0.0625}, + {-0.9, -0.5, -1.7, -0.0625, -0.375, -1.5}, + {-1, -0.5, 0.5, -0.0625, -0.375, 0.7} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(5) + end, + on_timer = function(pos, elapsed) + local pos2 = {x = pos.x, y = pos.y - 2, z = pos.z} + for i, ob in pairs(minetest.get_objects_inside_radius(pos2, 1)) do + if ob:get_luaentity() and ob:get_luaentity().wsc then + mesecon.receptor_on(pos) + return true + end + end + mesecon.receptor_off(pos) + return true + end + } +) \ No newline at end of file diff --git a/scripts/signs.lua b/scripts/signs.lua new file mode 100644 index 0000000..3f2b942 --- /dev/null +++ b/scripts/signs.lua @@ -0,0 +1,202 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +local snuma = 1 +for ii = 0, 9, 1 do + if ii == 1 then + snuma = 0 + end + minetest.register_node( + "portalgun:sign_numa" .. ii, + { + description = "Sign number (" .. ii .. ")", + tiles = {"portalgun_snum" .. ii .. ".png"}, + drop = "portalgun:sign_numa1", + drawtype = "nodebox", + groups = {mesecon = 2, portalnuma = 1, dig_immediate = 3, not_in_creative_inventory = snuma}, + sounds = wood_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + light_source = 3, + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0.4375, 0, 0.5, 0.5} + } + }, + after_place_node = function(pos, placer, itemstack) + local param2 = minetest.get_node(pos).param2 + local pos2 = portalgun_param2(pos, param2) + if minetest.get_node(pos2) and minetest.get_node(pos2).name == "air" then + minetest.set_node(pos2, {name = "portalgun:sign_numb1", param2 = param2}) + minetest.swap_node(pos, {name = "portalgun:sign_numa0", param2 = minetest.get_node(pos).param2}) + end + end, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not minetest.is_protected(pos, clicker:get_player_name()) then + local iin = ii + 1 + if iin == 10 then + iin = 0 + end + minetest.swap_node( + pos, + {name = "portalgun:sign_numa" .. iin, param2 = minetest.get_node(pos).param2} + ) + end + end, + on_punch = function(pos, node, player, pointed_thing) + local param2 = minetest.get_node(pos).param2 + local pos2 = portalgun_param2(pos, param2) + local node = minetest.get_node(pos2) + if node and minetest.get_node_group(node.name, "portalnumb") > 0 then + minetest.set_node(pos2, {name = "air"}) + end + end + } + ) + if snuma == 0 then + snuma = 1 + end + minetest.register_node( + "portalgun:sign_numb" .. ii, + { + description = "Sign number", + tiles = {"portalgun_snum" .. ii .. ".png"}, + drop = "portalgun:sign_numa1", + drawtype = "nodebox", + groups = {mesecon = 2, portalnumb = 1, dig_immediate = 3, not_in_creative_inventory = 1}, + sounds = wood_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + light_source = 3, + node_box = { + type = "fixed", + fixed = { + {-1, -0.5, 0.4375, -0.5, 0.5, 0.5} + } + }, + on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) + if not minetest.is_protected(pos, clicker:get_player_name()) then + local iin = ii + 1 + if iin == 10 then + iin = 0 + end + minetest.swap_node( + pos, + {name = "portalgun:sign_numb" .. iin, param2 = minetest.get_node(pos).param2} + ) + end + end, + on_punch = function(pos, node, player, pointed_thing) + local param2 = minetest.get_node(pos).param2 + local pos2 = portalgun_param2(pos, param2, true) + local node = minetest.get_node(pos2) + if node and minetest.get_node_group(node.name, "portalnuma") > 0 then + minetest.set_node(pos2, {name = "air"}) + end + end + } + ) +end +minetest.register_node( + "portalgun:sign1", + { + description = "Portal sign blue", + tiles = {"portalgun_testblock.png^portalgun_sign1.png"}, + inventory_image = "portalgun_testblock.png^portalgun_sign1.png", + drawtype = "nodebox", + groups = {snappy = 3, not_in_creative_inventory = 0}, + sounds = wood_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.45, 0.5, 0.5, 0.5} + } + } +) + +minetest.register_node( + "portalgun:sign2", + { + description = "Portal sign orange", + tiles = {"portalgun_testblock.png^portalgun_sign2.png"}, + inventory_image = "portalgun_testblock.png^portalgun_sign2.png", + drawtype = "nodebox", + groups = {snappy = 3, not_in_creative_inventory = 0}, + sounds = wood_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.45, 0.5, 0.5, 0.5} + } + } +) +minetest.register_node( + "portalgun:sign_v", + { + description = "Sign V", + tiles = {"portalgun_v.png"}, + inventory_image = "portalgun_v.png", + drop = "portalgun:sign_x", + drawtype = "nodebox", + groups = {mesecon = 2, snappy = 3, not_in_creative_inventory = 1}, + sounds = wood_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + light_source = 5, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.45, 0.5, 0.5, 0.5} + }, + mesecons = { + effector = { + action_off = function(pos, node) + minetest.swap_node(pos, {name = "portalgun:sign_x", param2 = minetest.get_node(pos).param2}) + end + } + } + } +) + +minetest.register_node( + "portalgun:sign_x", + { + description = "Sign X", + tiles = {"portalgun_x.png"}, + inventory_image = "portalgun_x.png", + drawtype = "nodebox", + groups = {mesecon = 2, snappy = 3, not_in_creative_inventory = 0}, + sounds = wood_sounds, + is_ground_content = false, + paramtype2 = "facedir", + paramtype = "light", + light_source = 3, + node_box = { + type = "fixed", + fixed = {-0.5, -0.5, 0.45, 0.5, 0.5, 0.5} + }, + mesecons = { + effector = { + action_on = function(pos, node) + minetest.swap_node(pos, {name = "portalgun:sign_v", param2 = minetest.get_node(pos).param2}) + end + } + } + } +) diff --git a/scripts/toxicwater.lua b/scripts/toxicwater.lua new file mode 100644 index 0000000..89b035a --- /dev/null +++ b/scripts/toxicwater.lua @@ -0,0 +1,58 @@ +minetest.register_node( + "portalgun:toxwater_1", + { + description = "Toxic water", + drawtype = "liquid", + tiles = {"portalgun_toxwat.png"}, + alpha = 190, + paramtype = "light", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + damage_per_second = 20, + liquidtype = "source", + liquid_alternative_flowing = "portalgun:toxwater_2", + liquid_alternative_source = "portalgun:toxwater_1", + liquid_viscosity = 2, + liquid_renewable = false, + liquid_range = 3, + post_effect_color = {a = 200, r = 119, g = 70, b = 16}, + groups = {water = 3, liquid = 3} + } +) + +minetest.register_node( + "portalgun:toxwater_2", + { + description = "Toxic water 2", + drawtype = "flowingliquid", + tiles = {name = "portalgun_toxwat.png", backface_culling = false}, + special_tiles = { + {name = "portalgun_toxwat.png", backface_culling = true}, + {name = "portalgun_toxwat.png", backface_culling = false} + }, + alpha = 190, + paramtype = "light", + paramtype2 = "flowingliquid", + walkable = false, + pointable = false, + diggable = false, + buildable_to = true, + is_ground_content = false, + drop = "", + drowning = 1, + damage_per_second = 4, + liquidtype = "flowing", + liquid_alternative_flowing = "portalgun:toxwater_2", + liquid_alternative_source = "portalgun:toxwater_1", + liquid_viscosity = 2, + liquid_renewable = false, + liquid_range = 3, + post_effect_color = {a = 200, r = 119, g = 70, b = 16}, + groups = {water = 3, liquid = 3, not_in_creative_inventory = 1} + } +) diff --git a/scripts/turrets.lua b/scripts/turrets.lua new file mode 100644 index 0000000..d7c1a6b --- /dev/null +++ b/scripts/turrets.lua @@ -0,0 +1,257 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:turretgun2", + { + description = "Sentry turret", + groups = {oddly_breakable_by_hand = 1, not_in_creative_inventory = 1}, + drop = "portalgun:turretgun", + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + sounds = stone_sounds, + tiles = {"portalgun_sentry_turret.png"}, + drawtype = "mesh", + mesh = "turret2.obj", + selection_box = { + type = "fixed", + fixed = { + {-0.3, -0.5, -0.3, 0.3, 1, 0.3} + } + }, + on_timer = function(pos, elapsed) + local p = minetest.get_node(pos).param2 + local pos1 = {x = pos.x, y = pos.y + 0.5, z = pos.z} + local d + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 10)) do + if + portalgun_visiable(pos1, ob) and + (ob:is_player() or + (ob:get_luaentity() and (ob:get_luaentity().type or ob:get_luaentity().portalgun == nil))) + then + local a = ob:get_pos() + if a.y < pos.y + 2 and a.y > pos.y - 1 then + a = {x = math.floor(a.x), y = math.floor(a.y), z = math.floor(a.z)} + if p == 3 and a.x > pos.x and a.z == pos.z then + d = {x = 20, y = 0, z = 0} + break + elseif p == 1 and a.x < pos.x and a.z == pos.z then + d = {x = -20, y = 0, z = 0} + break + elseif p == 2 and a.z > pos.z and a.x == pos.x then + d = {x = 0, y = 0, z = 20} + break + elseif p == 0 and a.z < pos.z and a.x == pos.x then + d = {x = 0, y = 0, z = -20} + break + end + end + end + end + local m = minetest.get_meta(pos) + if d then + m:set_int("stop", 0) + minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) + minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) + for i = 2, 5, 1 do + minetest.after( + i * 0.1, + function(pos, d) + minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) + minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) + end, + pos, + d + ) + end + else + if m:get_int("stop") == 1 then + minetest.set_node(pos, {name = "portalgun:turretgun", param2 = p}) + minetest.get_node_timer(pos):start(0.2) + else + m:set_int("stop", 1) + end + end + return true + end + } +) + +minetest.register_node( + "portalgun:turretgun", + { + description = "Sentry turret", + groups = {oddly_breakable_by_hand = 1}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + sounds = stone_sounds, + tiles = {"portalgun_sentry_turret.png"}, + drawtype = "mesh", + mesh = "turret1.obj", + selection_box = { + type = "fixed", + fixed = { + {-0.3, -0.5, -0.3, 0.3, 1, 0.3} + } + }, + on_construct = function(pos) + minetest.get_node_timer(pos):start(0.2) + end, + on_timer = function(pos, elapsed) + local p = minetest.get_node(pos).param2 + local pos1 = {x = pos.x, y = pos.y + 0.5, z = pos.z} + local d + for i, ob in pairs(minetest.get_objects_inside_radius(pos1, 10)) do + if + portalgun_visiable(pos1, ob) and + (ob:is_player() or + (ob:get_luaentity() and (ob:get_luaentity().type or ob:get_luaentity().portalgun == nil))) + then + local a = ob:get_pos() + if a.y < pos.y + 2 and a.y > pos.y - 1 then + a = {x = math.floor(a.x), y = math.floor(a.y), z = math.floor(a.z)} + if p == 3 and a.x > pos.x and a.z == pos.z then + d = {x = 20, y = 0, z = 0} + break + elseif p == 1 and a.x < pos.x and a.z == pos.z then + d = {x = -20, y = 0, z = 0} + break + elseif p == 2 and a.z > pos.z and a.x == pos.x then + d = {x = 0, y = 0, z = 20} + break + elseif p == 0 and a.z < pos.z and a.x == pos.x then + d = {x = 0, y = 0, z = -20} + break + end + end + end + end + + if d then + minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) + minetest.set_node(pos, {name = "portalgun:turretgun2", param2 = p}) + minetest.get_node_timer(pos):start(1) + minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) + for i = 2, 5, 1 do + minetest.after( + i * 0.1, + function(pos, d) + minetest.add_entity(pos1, "portalgun:bullet1"):set_velocity(d) + minetest.sound_play("portalgun_bullet1", {pos = pos, gain = 1, max_hear_distance = 15}) + end, + pos, + d + ) + end + end + return true + end + } +) + +function portalgun_visiable(pos, ob) + if ob == nil or ob:get_pos() == nil or ob:get_pos().y == nil then + return false + end + local ta = ob:get_pos() + local v = {x = pos.x - ta.x, y = pos.y - ta.y - 1, z = pos.z - ta.z} + v.y = v.y - 1 + local amount = (v.x ^ 2 + v.y ^ 2 + v.z ^ 2) ^ 0.5 + local d = + math.sqrt((pos.x - ta.x) * (pos.x - ta.x) + (pos.y - ta.y) * (pos.y - ta.y) + (pos.z - ta.z) * (pos.z - ta.z)) + v.x = (v.x / amount) * -1 + v.y = (v.y / amount) * -1 + v.z = (v.z / amount) * -1 + for i = 1, d, 1 do + local node = + minetest.registered_nodes[ + minetest.get_node({x = pos.x + (v.x * i), y = pos.y + (v.y * i), z = pos.z + (v.z * i)}).name + ] + if node.walkable then + return false + end + end + return true +end + +function portalgun_round(x) + if x % 2 ~= 0.5 then + return math.floor(x + 0.5) + end + return x - 0.5 +end + +function portalgun_ra2shoot(pos, ob) + local op = ob:get_pos() + local m = minetest.get_meta(pos) + local x = m:get_int("x") + local y = m:get_int("y") + local z = m:get_int("z") + local ox = portalgun_round(op.x) + local oy = portalgun_round(op.y) + local oz = portalgun_round(op.z) + if x == 1 and ox == pos.x and oz <= pos.z then + return true + end + if x == -1 and ox == pos.x and oz >= pos.z then + return true + end + if z == -1 and oz == pos.z and ox <= pos.x then + return true + end + if z == 1 and oz == pos.z and ox >= pos.x then + return true + end + return false +end + +minetest.register_entity( + "portalgun:bullet1", + { + hp_max = 1, + --physical = true, + --collisionbox={-0.01,-0.01,-0.01,0.01,0.01,0.01}, + pointable = false, + visual = "mesh", + mesh = "bullet.obj", + --yellow color as tiles + tiles = {"#color[yellow]"}, + initial_sprite_basepos = {x = 0, y = 0}, + portalgun = 2, + bullet = 1, + on_step = function(self, dtime) + self.timer = self.timer + dtime + self.timer2 = self.timer2 + dtime + local pos = self.object:get_pos() + local n = minetest.registered_nodes[minetest.get_node(self.object:get_pos()).name] + if self.timer > 1 or (n and n.walkable) then + self.object:remove() + return + end + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + if ob:is_player() then + if ob:get_hp() > 2 then + ob:set_hp(ob:get_hp() - 2) + else + ob:set_hp(0) + end + self.object:remove() + return + end + end + end, + timer = 0, + timer2 = 0 + } +) diff --git a/scripts/warntape.lua b/scripts/warntape.lua new file mode 100644 index 0000000..a7debfa --- /dev/null +++ b/scripts/warntape.lua @@ -0,0 +1,32 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +minetest.register_node( + "portalgun:warntape", + { + description = "Warntape", + groups = {dig_immediate = 3, not_in_creative_inventory = 0}, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + sounds = stone_sounds, + tiles = {"portalgun_warntape.png"}, + walkable = false, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-0.5, -0.5, 0.3125, 0.5, -0.4375, 0.5} + } + } + } +) diff --git a/scripts/weightedstoragecube.lua b/scripts/weightedstoragecube.lua new file mode 100644 index 0000000..56a8465 --- /dev/null +++ b/scripts/weightedstoragecube.lua @@ -0,0 +1,88 @@ +stone_sounds = {} +stone_sounds.footstep = {name = "stone_walk", gain = 1.0} +stone_sounds.dug = {name = "stone_break", gain = 1.0} +stone_sounds.place = {name = "block_place", gain = 1.0} +glass_sounds = {} +glass_sounds.footstep = {name = "glass_walk", gain = 1.0} +glass_sounds.dug = {name = "glass_break", gain = 1.0} +glass_sounds.place = {name = "block_place", gain = 1.0} +wood_sounds = {} +wood_sounds.footstep = {name = "wood_walk", gain = 1.0} +wood_sounds.dug = {name = "wood_break", gain = 1.0} +wood_sounds.place = {name = "block_place", gain = 1.0} +new = 0 +local ptgwsc = { + {"weightedstoragecube.png", "portalgun_presplat.png", "(blue)"}, + {"weightedstoragecube2.png", "portalgun_presplat2.png", "(orange)"}, + {"weightedstoragecube3.png", "portalgun_presplat3.png", "(yellow)"}, + {"weightedstoragecube4.png", "portalgun_presplat4.png", "(green)"}, + {"weightedcompanioncube.png", "portalgun_presplat.png", "(blue companion)"}, + {"weightedcompanioncube2.png", "portalgun_presplat2.png", "(orange companion)"}, + {"weightedcompanioncube3.png", "portalgun_presplat3.png", "(yellow companion)"}, + {"weightedcompanioncube4.png", "portalgun_presplat4.png", "(green companion)"} +} + +for ii = 1, #ptgwsc, 1 do + minetest.register_craftitem( + "portalgun:wscube" .. ii, + { + description = "Weighted storage cube " .. ptgwsc[ii][3], + inventory_image = minetest.inventorycube(ptgwsc[ii][1]), + on_place = function(itemstack, user, pointed_thing) + if pointed_thing.type == "node" then + new = 1 + local m = minetest.add_entity(pointed_thing.above, "portalgun:wsc" .. ii) + m:set_acceleration({x = 0, y = -10, z = 0}) + itemstack:take_item() + end + return itemstack + end + } + ) + + minetest.register_entity( + "portalgun:wsc" .. ii, + { + hp_max = 100, + physical = true, + weight = 5, + collisionbox = {-0.6, -0.6, -0.6, 0.6, 0.6, 0.6}, + visual = "cube", + visual_size = {x = 1.1, y = 1.1}, + textures = {ptgwsc[ii][1], ptgwsc[ii][1], ptgwsc[ii][1], ptgwsc[ii][1], ptgwsc[ii][1], ptgwsc[ii][1]}, + initial_sprite_basepos = {x = 0, y = 0}, + is_visible = true, + makes_footstep_sound = true, + automatic_rotate = 0, + portalgun = 2, + wsc = ii, + on_activate = function(self, staticdata) + if new == 0 then + self.object:remove() + return self + end + new = 0 + end, + on_step = function(self, dtime) + self.timer = self.timer + dtime + if self.timer < 1 then + return self + end + self.timer = 0 + self.object:set_acceleration({x = 0, y = -10, z = 0}) + self.timer2 = self.timer2 + 1 + if self.timer2 > 4 then + self.timer2 = 0 + for i, ob in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 20)) do + if ob:is_player() then + return true + end + end + self.object:set_hp(0) + end + end, + timer = 0, + timer2 = 0 + } + ) +end -- of for # diff --git a/stuff.lua b/stuff.lua deleted file mode 100644 index fdbfae2..0000000 --- a/stuff.lua +++ /dev/null @@ -1,606 +0,0 @@ -stone_sounds = {} -stone_sounds.footstep = {name="stone_walk", gain=1.0} -stone_sounds.dug = {name="stone_break", gain=1.0} -stone_sounds.place = {name="block_place", gain=1.0} -glass_sounds = {} -glass_sounds.footstep = {name="glass_walk", gain=1.0} -glass_sounds.dug = {name="glass_break", gain=1.0} -glass_sounds.place = {name="block_place", gain=1.0} -wood_sounds = {} -wood_sounds.footstep = {name="wood_walk", gain=1.0} -wood_sounds.dug = {name="wood_break", gain=1.0} -wood_sounds.place = {name="block_place", gain=1.0} -local snuma=1 -for ii = 0, 9, 1 do -if ii==1 then snuma=0 end -minetest.register_node("portalgun:sign_numa".. ii, { - description = "Sign number (" .. ii ..")", - tiles = {"portalgun_snum" .. ii ..".png"}, - drop="portalgun:sign_numa1", - drawtype = "nodebox", - groups = {mesecon=2,portalnuma=1,dig_immediate = 3, not_in_creative_inventory=snuma}, - sounds = wood_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - light_source = 3, - node_box = { - type = "fixed", - fixed = { - {-0.5, -0.5, 0.4375, 0, 0.5, 0.5}, - } - }, -after_place_node = function(pos, placer, itemstack) - local param2=minetest.get_node(pos).param2 - local pos2=portalgun_param2(pos,param2) - if minetest.get_node(pos2) and minetest.get_node(pos2).name=="air" then - minetest.set_node(pos2,{name="portalgun:sign_numb1",param2=param2}) - minetest.swap_node(pos, {name="portalgun:sign_numa0", param2=minetest.get_node(pos).param2}) - end - end, - on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) - if not minetest.is_protected(pos,clicker:get_player_name()) then - local iin=ii+1 - if iin==10 then iin=0 end - minetest.swap_node(pos, {name="portalgun:sign_numa".. iin, param2=minetest.get_node(pos).param2}) - end - end, - on_punch = function(pos, node, player, pointed_thing) - local param2=minetest.get_node(pos).param2 - local pos2=portalgun_param2(pos,param2) - local node=minetest.get_node(pos2) - if node and minetest.get_node_group(node.name, "portalnumb")>0 then - minetest.set_node(pos2, {name = "air"}) - end - end, - - -}) -if snuma==0 then snuma=1 end -minetest.register_node("portalgun:sign_numb".. ii, { - description = "Sign number", - tiles = {"portalgun_snum" .. ii ..".png"}, - drop="portalgun:sign_numa1", - drawtype = "nodebox", - groups = {mesecon=2,portalnumb=1,dig_immediate = 3, not_in_creative_inventory=1}, - sounds = wood_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - light_source = 3, - node_box = { - type = "fixed", - fixed = { - {-1, -0.5, 0.4375, -0.5, 0.5, 0.5}, - } - }, - on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) - if not minetest.is_protected(pos,clicker:get_player_name()) then - local iin=ii+1 - if iin==10 then iin=0 end - minetest.swap_node(pos, {name="portalgun:sign_numb".. iin, param2=minetest.get_node(pos).param2}) - end - end, - on_punch = function(pos, node, player, pointed_thing) - local param2=minetest.get_node(pos).param2 - local pos2=portalgun_param2(pos,param2,true) - local node=minetest.get_node(pos2) - if node and minetest.get_node_group(node.name, "portalnuma")>0 then - minetest.set_node(pos2, {name = "air"}) - end - end, -}) -end - -minetest.register_node("portalgun:turretgun2", { - description = "Sentry turret", - groups = {oddly_breakable_by_hand=1,not_in_creative_inventory=1}, - drop="portalgun:turretgun", - paramtype = "light", - paramtype2 = "facedir", - sunlight_propagates = true, - sounds = stone_sounds, - tiles = {"portalgun_sentry_turret.png"}, - drawtype = "mesh", - mesh="torret2.obj", - selection_box = { - type = "fixed", - fixed = { - {-0.3, -0.5, -0.3, 0.3, 1,0.3}, - } - }, - on_timer=function(pos, elapsed) - local p=minetest.get_node(pos).param2 - local pos1={x=pos.x,y=pos.y+0.5,z=pos.z} - local d - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 10)) do - if portalgun_visiable(pos1,ob) and (ob:is_player() or (ob:get_luaentity() and (ob:get_luaentity().type or ob:get_luaentity().portalgun==nil))) then - local a=ob:get_pos() - if a.ypos.y-1 then - a={x=math.floor(a.x),y=math.floor(a.y),z=math.floor(a.z)} - if p==3 and a.x>pos.x and a.z==pos.z then - d={x=20,y=0,z=0} - break - elseif p==1 and a.xpos.z and a.x==pos.x then - d={x=0,y=0,z=20} - break - elseif p==0 and a.zpos.y-1 then - a={x=math.floor(a.x),y=math.floor(a.y),z=math.floor(a.z)} - if p==3 and a.x>pos.x and a.z==pos.z then - d={x=20,y=0,z=0} - break - elseif p==1 and a.xpos.z and a.x==pos.x then - d={x=0,y=0,z=20} - break - elseif p==0 and a.z=pos.z then - return true - end - if z==-1 and oz==pos.z and ox<=pos.x then - return true - end - if z==1 and oz==pos.z and ox>=pos.x then - return true - end - return false -end - -minetest.register_node("portalgun:secam_off", { - description = "Security cam (off)" , - tiles = {"portalgun_scam.png"}, - drawtype = "nodebox", - walkable=false, - groups = {dig_immediate = 3}, - sounds = glass_sounds, - is_ground_content = false, - paramtype = "light", - paramtype2 = "facedir", - node_box = {type="fixed", - fixed={ {-0.2, -0.5, -0.2, 0.2, -0.4, 0.2}, - {-0.1, -0.2, -0.1, 0.1, -0.4, 0.1}} - }, - on_place = minetest.rotate_node, - on_construct = function(pos) - minetest.get_meta(pos):set_string("infotext","click to activate") - end, -on_rightclick = function(pos, node, player, itemstack, pointed_thing) - minetest.set_node(pos, {name ="portalgun:secam", param1 = node.param1, param2 = node.param2}) - minetest.get_node_timer(pos):start(1) -end, -}) - -minetest.register_node("portalgun:secam", { - description = "Security cam", - tiles = {"portalgun_scam.png"}, - drawtype = "nodebox", - walkable=false, - groups = {dig_immediate = 3,stone=1,not_in_creative_inventory=1}, - sounds = glass_sounds, - is_ground_content = false, - paramtype = "light", - paramtype2 = "facedir", - drop="portalgun:secam_off", - node_box = {type="fixed", - fixed={ {-0.2, -0.5, -0.2, 0.2, -0.4, 0.2}, - {-0.1, -0.2, -0.1, 0.1, -0.4, 0.1}} - }, -on_timer=function(pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 10)) do - if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().itemstring==nil and ob:get_luaentity().portalgun==nil) then - if portalgun_visiable(pos,ob) then - local v=ob:get_pos() - if not ob:get_luaentity() then v.y=v.y+1 end - local s={x=(v.x-pos.x)*3,y=(v.y-pos.y)*3,z=(v.z-pos.z)*3} - local m=minetest.add_entity(pos, "portalgun:bullet1") - m:set_velocity(s) - m:set_acceleration(s) - minetest.sound_play("portalgun_bullet1", {pos=pos, gain = 1, max_hear_distance = 15,}) - minetest.after((math.random(1,9)*0.1), function(pos,s,v) - local m=minetest.add_entity(pos, "portalgun:bullet1") - m:set_velocity(s) - m:set_acceleration(s) - minetest.sound_play("portalgun_bullet1", {pos=pos, gain = 1, max_hear_distance = 15,}) - end, pos,s,v) - end - end - end - return true - end, -}) - ---register command for admins to build a testblock at the players position -minetest.register_chatcommand("testblock", { - params = "", - description = "builds a testblock at the players position", - privs = {server=true}, - func = function(name, param) - local player = minetest.get_player_by_name(name) - local pos = player:get_pos() - minetest.set_node(pos, {name = "portalgun:testblock"}) - end, -}) - -minetest.register_entity("portalgun:bullet1",{ - hp_max = 1, - --physical = true, - --collisionbox={-0.01,-0.01,-0.01,0.01,0.01,0.01}, - pointable=false, - visual = "mesh", - mesh = "bullet.obj", - --yellow color as tiles - tiles = {"#color[yellow]"}, - initial_sprite_basepos = {x=0, y=0}, - portalgun=2, - bullet=1, -on_step= function(self, dtime) - self.timer=self.timer+dtime - self.timer2=self.timer2+dtime - local pos=self.object:get_pos() - local n=minetest.registered_nodes[minetest.get_node(self.object:get_pos()).name] - if self.timer>1 or (n and n.walkable) then - self.object:remove() - return - end - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do - if ob:is_player() then - if ob:get_hp() > 2 then - ob:set_hp(ob:get_hp()-2) - else - ob:set_hp(0) - end - self.object:remove() - return - end - end - end, - timer=0, - timer2=0, -}) - -minetest.register_node("portalgun:sign1", { - description = "Portal sign blue", - tiles = {"portalgun_testblock.png^portalgun_sign1.png"}, - inventory_image = "portalgun_testblock.png^portalgun_sign1.png", - drawtype = "nodebox", - groups = {snappy = 3, not_in_creative_inventory=0}, - sounds = wood_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - node_box = { - type="fixed", - fixed={-0.5,-0.5,0.45,0.5,0.5,0.5}}, -}) - -minetest.register_node("portalgun:sign2", { - description = "Portal sign orange", - tiles = {"portalgun_testblock.png^portalgun_sign2.png"}, - inventory_image = "portalgun_testblock.png^portalgun_sign2.png", - drawtype = "nodebox", - groups = {snappy = 3, not_in_creative_inventory=0}, - sounds = wood_sounds, - is_ground_content = false, - paramtype2 = "facedir", - paramtype = "light", - node_box = { - type="fixed", - fixed={-0.5,-0.5,0.45,0.5,0.5,0.5}}, -}) diff --git a/textures/weightedcompanioncube.png b/textures/weightedcompanioncube.png new file mode 100644 index 0000000000000000000000000000000000000000..7a2225d31e3dc0d8cc6cee1d0db9c9ce450f0dc4 GIT binary patch literal 11549 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 literal 0 HcmV?d00001 diff --git a/textures/weightedcompanioncube2.png b/textures/weightedcompanioncube2.png new file mode 100644 index 0000000000000000000000000000000000000000..2db7c7271ae0843215141b6b10ceb8c63b9ae1d3 GIT binary patch literal 11701 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 literal 0 HcmV?d00001 diff --git a/textures/weightedcompanioncube3.png b/textures/weightedcompanioncube3.png new file mode 100644 index 0000000000000000000000000000000000000000..040140d74fdd5ea0cf1c517dfbfedd0ba407ef72 GIT binary patch literal 11661 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 literal 0 HcmV?d00001 diff --git a/textures/weightedcompanioncube4.png b/textures/weightedcompanioncube4.png new file mode 100644 index 0000000000000000000000000000000000000000..5285c5e42cc7f34cb9cebf0ef9df2646cb17c2a1 GIT binary patch literal 11699 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 then - self.timer2=0 - for i, ob in pairs(minetest.get_objects_inside_radius(self.object:get_pos(), 20)) do - if ob:is_player() then - return true - end - end - self.object:set_hp(0) - end - end, - timer=0, - timer2=0, -}) - -minetest.register_node("portalgun:wscspawner"..ii, { - description = "Weighted storage cube spawner " ..ptgwsc[ii][3], - tiles = {ptgwsc[ii][1]}, - groups = {cracky = 1, not_in_creative_inventory=0}, - paramtype = "light", - paramtype2="facedir", - sunlight_propagates = true, - light_source = 14, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, - {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, - {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, - {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, - {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, - } - }, - on_construct = function(pos) - minetest.get_node_timer(pos):start(5) - end, - on_timer = function (pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 40)) do - if ob:get_luaentity() and ob:get_luaentity().wsc==ii then - return true - end - end - portalgun.new=1 - local m=minetest.add_entity(pos, "portalgun:wsc" ..ii) - m:set_acceleration({x=0,y=-10,z=0}) - return true - end, -}) - -minetest.register_node("portalgun:plantform1_" ..ii, { - description = "Pressure platform " .. ptgwsc[ii][3], - tiles = {ptgwsc[ii][2],"cloud.png","cloud.png","cloud.png","cloud.png","cloud.png"}, - groups = {mesecon = 2,cracky = 1, not_in_creative_inventory=0}, - mesecons = {receptor = {state = "off"}}, - paramtype = "light", - sunlight_propagates = true, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, - {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, - {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, - {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, - {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, - {-0.5, -0.5, -0.5, 0.5, -0.3125, 0.5}, - } - }, - on_construct = function(pos) - minetest.get_node_timer(pos):start(2) - end, - on_timer = function (pos, elapsed) - if not mesecon then return false end - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do - if ob:get_luaentity() and ob:get_luaentity().wsc==ii then - local node=minetest.get_node(pos) - mesecon.receptor_on(pos) - minetest.set_node(pos, {name ="portalgun:plantform2_"..ii, param1 = node.param1, param2 = node.param2}) - end - return true - end - return true - end, -}) - -minetest.register_node("portalgun:plantform2_"..ii, { - description = "Pressure platform", - tiles = {ptgwsc[ii][2],"cloud.png","cloud.png","cloud.png","cloud.png","cloud.png"}, - drop="portalgun:plantform1_"..ii, - groups = {mesecon = 2,cracky = 1, not_in_creative_inventory=1}, - mesecons = {receptor = {state = "on"}}, - paramtype = "light", - sunlight_propagates = true, - light_source = 14, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, - {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, - {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, - {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, - {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, - } - }, - on_construct = function(pos) - minetest.get_node_timer(pos):start(2) - end, - on_timer = function (pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do - if ob:get_luaentity() and ob:get_luaentity().wsc==ii then - return true - end - end - mesecon.receptor_off(pos) - local node=minetest.get_node(pos) - minetest.set_node(pos, {name ="portalgun:plantform1_"..ii, param1 = node.param1, param2 = node.param2}) - return true - end, -}) - - -end -- of for # - - -minetest.register_node("portalgun:plantform_nu1", { - description = "Pressure platform (player or cube)", - tiles = {"portalgun_presplat5.png","cloud.png","cloud.png","cloud.png","cloud.png","cloud.png"}, - groups = {mesecon = 2,cracky = 1, not_in_creative_inventory=0}, - mesecons = {receptor = {state = "off"}}, - paramtype = "light", - sunlight_propagates = true, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, - {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, - {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, - {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, - {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, - {-0.5, -0.5, -0.5, 0.5, -0.3125, 0.5}, - } - }, - on_construct = function(pos) - minetest.get_node_timer(pos):start(2) - end, - on_timer = function (pos, elapsed) - if not mesecon then return false end - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do - if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().wsc) then - local node=minetest.get_node(pos) - mesecon.receptor_on(pos) - minetest.set_node(pos, {name ="portalgun:plantform_nu2", param1 = node.param1, param2 = node.param2}) - end - return true - end - return true - end, -}) - -minetest.register_node("portalgun:plantform_nu2", { - description = "Pressure platform", - tiles = {"portalgun_presplat5.png","cloud.png","cloud.png","cloud.png","cloud.png","cloud.png"}, - drop="portalgun:plantform_nu1", - groups = {mesecon = 2,cracky = 1, not_in_creative_inventory=1}, - mesecons = {receptor = {state = "on"}}, - paramtype = "light", - sunlight_propagates = true, - light_source = 14, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type = "fixed", - fixed = { - {-0.7, -0.5, -0.7, 0.7, -0.375, 0.7}, - {0.7, -0.5, -0.1875, 0.9, -0.4375, 0.1875}, - {-0.9, -0.5, -0.1875, -0.7, -0.4375, 0.1875}, - {-0.1875, -0.5, -0.9, 0.1875, -0.4375, -0.7}, - {-0.1875, -0.5, 0.7, 0.1875, -0.4375, 0.9}, - } - }, - on_construct = function(pos) - minetest.get_node_timer(pos):start(2) - end, - on_timer = function (pos, elapsed) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1)) do - if ob:is_player() or (ob:get_luaentity() and ob:get_luaentity().wsc) then - return true - end - end - mesecon.receptor_off(pos) - local node=minetest.get_node(pos) - minetest.set_node(pos, {name ="portalgun:plantform_nu1", param1 = node.param1, param2 = node.param2}) - return true - end, -}) - - -minetest.register_node("portalgun:planthole", { - description = "Plathole (activate by any cube, 2 blocks under)", - tiles = {"cloud.png"}, - groups = {mesecon = 2,cracky = 1}, - mesecons = {receptor = {state = "off"}}, - paramtype = "light", - sunlight_propagates = true, - sounds = stone_sounds, - drawtype="nodebox", - node_box = { - type = "fixed", - fixed = { - {-1.5, -0.5, -1.5, 0.5, -0.25, -1.3}, - {-1.5, -0.5, 0.3, 0.5, -0.25, 0.5}, - {0.3, -0.5, -1.5, 0.5, -0.25, 0.5}, - {-1.5, -0.5, -1.5, -1.3, -0.25, 0.5}, - {0.5, -0.5, -0.9, 0.7, -0.375, -0.0625}, - {-1.7, -0.5, -0.9, -1.5, -0.3125, -0.0625}, - {-0.9, -0.5, -1.7, -0.0625, -0.375, -1.5}, - {-1, -0.5, 0.5, -0.0625, -0.375, 0.7}, - } - }, - on_construct = function(pos) - minetest.get_node_timer(pos):start(5) - end, - on_timer = function (pos, elapsed) - local pos2={x=pos.x,y=pos.y-2,z=pos.z} - for i, ob in pairs(minetest.get_objects_inside_radius(pos2, 1)) do - if ob:get_luaentity() and ob:get_luaentity().wsc then - mesecon.receptor_on(pos) - return true - end - end - mesecon.receptor_off(pos) - return true - end, -}) - - - -minetest.register_node("portalgun:objdestroyer_1", { - description = "Object destroyer (destroys on active)", - tiles = {"portalgun_testblock.png^[colorize:#FF0000aa"}, - groups = {cracky = 2,mesecon=1}, - sounds = stone_sounds, - mesecons = {effector = { - action_on = function (pos, node) - minetest.set_node(pos, {name ="portalgun:objdestroyer_2"}) - for i, ob in pairs(minetest.get_objects_inside_radius(pos, 5)) do - if ob:get_luaentity() then - ob:set_hp(0) - end - end - end - }} -}) -minetest.register_node("portalgun:objdestroyer_2", { - description = "Obj destroyer", - tiles = {"portalgun_testblock.png^[colorize:#FF0000cc"}, - groups = {cracky=2,mesecon=1,not_in_creative_inventory=1}, - sunlight_propagates = true, - drop="portalgun:objdestroyer_1", - paramtype="light", - light_source = 14, - mesecons = {conductor = { - state = mesecon.state.on, - offstate = "portalgun:objdestroyer_1", - }}, -})