From 7ac25d3a5c21b20e1836ffdb088c7671d8c0307c Mon Sep 17 00:00:00 2001 From: AiTechEye <40591179+AiTechEye@users.noreply.github.com> Date: Tue, 26 Jun 2018 09:06:05 +0200 Subject: [PATCH] Add files via upload --- aliveai_threats/crystal.lua | 328 ++ aliveai_threats/depends.txt | 5 + aliveai_threats/eyes.lua | 252 ++ aliveai_threats/flowerattack.lua | 77 + aliveai_threats/fort.lua | 207 ++ aliveai_threats/init.lua | 2921 +++++++++++++++++ aliveai_threats/lab.lua | 712 ++++ .../models/aliveai_threats_crystal.obj | 94 + .../models/aliveai_threats_crystals.obj | 549 ++++ aliveai_threats/readme.txt | 1 + aliveai_threats/sec.lua | 427 +++ .../sounds/aliveai_threats_bullet1.ogg | Bin 0 -> 12120 bytes aliveai_threats/sounds/aliveai_threats_on.ogg | Bin 0 -> 13304 bytes .../textures/aliveai_threats_acidman.png | Bin 0 -> 738 bytes .../textures/aliveai_threats_bee.png | Bin 0 -> 140 bytes .../textures/aliveai_threats_c4.png | Bin 0 -> 3800 bytes .../aliveai_threats_c4_controller.png | Bin 0 -> 2254 bytes .../textures/aliveai_threats_cam1.png | Bin 0 -> 301 bytes .../textures/aliveai_threats_cam2.png | Bin 0 -> 270 bytes .../textures/aliveai_threats_chainfence.png | Bin 0 -> 163 bytes .../textures/aliveai_threats_cockroach.png | Bin 0 -> 416 bytes .../aliveai_threats_crystal_grass.png | Bin 0 -> 271 bytes .../textures/aliveai_threats_crystals.png | Bin 0 -> 1460 bytes .../textures/aliveai_threats_eyes.png | Bin 0 -> 189 bytes .../textures/aliveai_threats_eyes_mad.png | Bin 0 -> 205 bytes .../textures/aliveai_threats_fangs.png | Bin 0 -> 297 bytes .../textures/aliveai_threats_fangs2.png | Bin 0 -> 275 bytes .../textures/aliveai_threats_gassman.png | Bin 0 -> 790 bytes .../textures/aliveai_threats_gassman2.png | Bin 0 -> 738 bytes .../textures/aliveai_threats_i.png | Bin 0 -> 126 bytes .../aliveai_threats_mind_manipulator.png | Bin 0 -> 514 bytes .../aliveai_threats_natural_monster.png | Bin 0 -> 184 bytes .../textures/aliveai_threats_ninja.png | Bin 0 -> 250 bytes .../textures/aliveai_threats_nitrogen.png | Bin 0 -> 1625 bytes .../textures/aliveai_threats_nitrogenblow.png | Bin 0 -> 1918 bytes .../textures/aliveai_threats_pull.png | Bin 0 -> 1067 bytes .../aliveai_threats_quantum_monster.png | Bin 0 -> 266 bytes ...aliveai_threats_quantum_monster_lights.png | Bin 0 -> 383 bytes .../textures/aliveai_threats_quantumcore.png | Bin 0 -> 1744 bytes .../textures/aliveai_threats_slime.png | Bin 0 -> 1307 bytes .../aliveai_threats_stubborn_monster.png | Bin 0 -> 1312 bytes .../aliveai_threats_stubborn_monster1.png | Bin 0 -> 6686 bytes .../aliveai_threats_stubborn_monster2.png | Bin 0 -> 1309 bytes .../aliveai_threats_stubborn_monster3.png | Bin 0 -> 1329 bytes .../textures/aliveai_threats_terminator.png | Bin 0 -> 1926 bytes .../aliveai_threats_terminator_bronze.png | Bin 0 -> 2051 bytes .../textures/aliveai_threats_testbottle.png | Bin 0 -> 198 bytes .../aliveai_threats_testbottle_containin.png | Bin 0 -> 214 bytes aliveai_threats/tree.lua | 210 ++ 49 files changed, 5783 insertions(+) create mode 100644 aliveai_threats/crystal.lua create mode 100644 aliveai_threats/depends.txt create mode 100644 aliveai_threats/eyes.lua create mode 100644 aliveai_threats/flowerattack.lua create mode 100644 aliveai_threats/fort.lua create mode 100644 aliveai_threats/init.lua create mode 100644 aliveai_threats/lab.lua create mode 100644 aliveai_threats/models/aliveai_threats_crystal.obj create mode 100644 aliveai_threats/models/aliveai_threats_crystals.obj create mode 100644 aliveai_threats/readme.txt create mode 100644 aliveai_threats/sec.lua create mode 100644 aliveai_threats/sounds/aliveai_threats_bullet1.ogg create mode 100644 aliveai_threats/sounds/aliveai_threats_on.ogg create mode 100644 aliveai_threats/textures/aliveai_threats_acidman.png create mode 100644 aliveai_threats/textures/aliveai_threats_bee.png create mode 100644 aliveai_threats/textures/aliveai_threats_c4.png create mode 100644 aliveai_threats/textures/aliveai_threats_c4_controller.png create mode 100644 aliveai_threats/textures/aliveai_threats_cam1.png create mode 100644 aliveai_threats/textures/aliveai_threats_cam2.png create mode 100644 aliveai_threats/textures/aliveai_threats_chainfence.png create mode 100644 aliveai_threats/textures/aliveai_threats_cockroach.png create mode 100644 aliveai_threats/textures/aliveai_threats_crystal_grass.png create mode 100644 aliveai_threats/textures/aliveai_threats_crystals.png create mode 100644 aliveai_threats/textures/aliveai_threats_eyes.png create mode 100644 aliveai_threats/textures/aliveai_threats_eyes_mad.png create mode 100644 aliveai_threats/textures/aliveai_threats_fangs.png create mode 100644 aliveai_threats/textures/aliveai_threats_fangs2.png create mode 100644 aliveai_threats/textures/aliveai_threats_gassman.png create mode 100644 aliveai_threats/textures/aliveai_threats_gassman2.png create mode 100644 aliveai_threats/textures/aliveai_threats_i.png create mode 100644 aliveai_threats/textures/aliveai_threats_mind_manipulator.png create mode 100644 aliveai_threats/textures/aliveai_threats_natural_monster.png create mode 100644 aliveai_threats/textures/aliveai_threats_ninja.png create mode 100644 aliveai_threats/textures/aliveai_threats_nitrogen.png create mode 100644 aliveai_threats/textures/aliveai_threats_nitrogenblow.png create mode 100644 aliveai_threats/textures/aliveai_threats_pull.png create mode 100644 aliveai_threats/textures/aliveai_threats_quantum_monster.png create mode 100644 aliveai_threats/textures/aliveai_threats_quantum_monster_lights.png create mode 100644 aliveai_threats/textures/aliveai_threats_quantumcore.png create mode 100644 aliveai_threats/textures/aliveai_threats_slime.png create mode 100644 aliveai_threats/textures/aliveai_threats_stubborn_monster.png create mode 100644 aliveai_threats/textures/aliveai_threats_stubborn_monster1.png create mode 100644 aliveai_threats/textures/aliveai_threats_stubborn_monster2.png create mode 100644 aliveai_threats/textures/aliveai_threats_stubborn_monster3.png create mode 100644 aliveai_threats/textures/aliveai_threats_terminator.png create mode 100644 aliveai_threats/textures/aliveai_threats_terminator_bronze.png create mode 100644 aliveai_threats/textures/aliveai_threats_testbottle.png create mode 100644 aliveai_threats/textures/aliveai_threats_testbottle_containin.png create mode 100644 aliveai_threats/tree.lua diff --git a/aliveai_threats/crystal.lua b/aliveai_threats/crystal.lua new file mode 100644 index 0000000..ca59087 --- /dev/null +++ b/aliveai_threats/crystal.lua @@ -0,0 +1,328 @@ +minetest.register_craft( { + output = "aliveai_threats:crystal_small 3", + recipe = { + {"aliveai_threats:crystal_big"}, + } +}) + +minetest.register_craft( { + output = "aliveai_threats:crystal_small 2", + recipe = { + {"aliveai_threats:crystal_medium"}, + } +}) + +minetest.register_craft( { + output = "aliveai_threats:chainfence 3", + recipe = { + {"default:steel_ingot","","default:steel_ingot"}, + {"default:steel_ingot","aliveai_threats:crystal_small","default:steel_ingot"}, + {"default:steel_ingot","","default:steel_ingot"}, + } +}) + +if not aliveai_electric then + aliveai_electric={} + aliveai_electric.hit=function(ob,h) + aliveai.punchdmg(ob,h) + end +end + +aliveai.create_bot({ + attack_players=1, + name="crystal", + team="crystal", + texture="aliveai_threats_crystals.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["aliveai_threats:crystalrod"]=1}, + type="monster", + dmg=5, + hp=40, + name_color="", + coming=0, + smartfight=0, + attack_chance=2, + death=function(self,puncher,pos) + minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 5,}) + if not self.ex then + self.ex=true + aliveai_threats.crystalblow(pos) + aliveai_threats.crystalblow(pos) + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 1, + maxsize = 4, + texture = "aliveai_threats_crystals", + collisiondetection = true, + }) + end + return self + end +}) + + +aliveai_threats.crystalblow=function(pos) + local nodes=aliveai.get_nodes(pos,5,2,{"default:stone"}) + for _, nodepos in pairs(nodes) do + if not minetest.is_protected(nodepos,"") and aliveai.distance(nodepos,pos)<5 then + local n=minetest.get_node(nodepos).name + if minetest.get_item_group(n,"snappy")>0 then + local na={"aliveai_threats:crystal_medium","aliveai_threats:crystal_big","aliveai_threats:crystal_small","aliveai_threats:crystal_grass"} + minetest.set_node(nodepos,{name=na[math.random(1,4)]}) + elseif minetest.get_item_group(n,"choppy")>0 then + minetest.set_node(nodepos,{name="aliveai_threats:crystal_block"}) + elseif minetest.get_item_group(n,"soil")>0 then + minetest.set_node(nodepos,{name="aliveai_threats:crystal_soil"}) + end + end + end + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 5)) do + aliveai_electric.hit(ob,10) + end +end + +minetest.register_tool("aliveai_threats:crystalrod", { + description = "Crystal rod", + inventory_image = "aliveai_threats_crystals.png", + range = 15, + groups = {not_in_creative_inventory=1}, + on_use=function(itemstack, user, pointed_thing) + if user:get_luaentity() then user=user:get_luaentity() end + local typ=pointed_thing.type + local pos1=user:get_pos() + pos1.y=pos1.y+1.5 + local pos2 + if typ=="object" then + pos2=pointed_thing.ref:get_pos() + elseif typ=="node" then + pos2=pointed_thing.under + elseif typ=="nothing" then + local dir + if user:get_luaentity() then + if user:get_luaentity().aliveai and user:get_luaentity().fight then + local dir=aliveai.get_dir(user:get_luaentity(),user:get_luaentity().fight) + pos2={x=pos1.x+(dir.x*30),y=pos1.y+(dir.y*30),z=pos1.z+(dir.z*30)} + else + pos2=aliveai.pointat(user:get_luaentity(),30) + end + else + local dir=user:get_look_dir() + pos2={x=pos1.x+(dir.x*30),y=pos1.y+(dir.y*30),z=pos1.z+(dir.z*30)} + end + else + return itemstack + end + local d=math.floor(aliveai.distance(pos1,pos2)+0.5) + local dir={x=(pos1.x-pos2.x)/-d,y=(pos1.y-pos2.y)/-d,z=(pos1.z-pos2.z)/-d} + local p1=pos1 + for i=0,d,1 do + p1={x=pos1.x+(dir.x*i),y=pos1.y+(dir.y*i),z=pos1.z+(dir.z*i)} + if aliveai.def(p1,"walkable") then + break + end + end + + if p1.x~=p1.x or p1.y~=p1.y or p1.z~=p1.z then + return itemstack + end + itemstack:add_wear(65535/20) + aliveai_threats.crystalblow(p1) + minetest.sound_play("aliveai_electric_lightning", {pos = p1,max_hear_distance = 5,gain = 0.1,}) + minetest.sound_play("aliveai_electric_lightning", {pos = pos1,max_hear_distance = 5,gain = 0.1,}) + return itemstack + end, +}) + + +minetest.register_node("aliveai_threats:crystal_big", { + description = "Big crystal", + drawtype = "mesh", + mesh = "aliveai_threats_crystals.obj", + visual_scale = 0.3, + wield_scale = {x=1, y=1, z=1}, + alpha = 20, + tiles = { + { + name = "aliveai_threats_crystals.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + damage_per_second = 10, + walkable = false, + is_ground_content = false, + light_source=3, + selection_box = { + type = "fixed", + fixed = {-1, -1, -1, 1, 1, 1} + }, + collision_box = { + type = "fixed", + fixed = {{-2, -2, -2, 2, 2, 2},}}, + groups = {cracky = 1, level = 3}, + on_punch = function(pos, node, puncher, pointed_thing) + aliveai_electric.hit(pointed_thing.ref,30) + end, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" or pointed_thing.type=="nothing" then return itemstack end + local pvp=minetest.setting_getbool("enable_pvp") + local ob=pointed_thing.ref + if ob:is_player() and pvp==false then return itemstack end + aliveai_electric.hit(puncher,30) + itemstack:take_item(1) + return itemstack + end, +}) + +minetest.register_node("aliveai_threats:crystal_medium", { + description = "Medium crystal", + drawtype = "mesh", + mesh = "aliveai_threats_crystals.obj", + visual_scale = 0.2, + wield_scale = {x=1, y=1, z=1}, + alpha = 20, + tiles = { + { + name = "aliveai_threats_crystals.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + damage_per_second = 4, + walkable = false, + is_ground_content = false, + light_source=3, + groups = {cracky = 2, level = 2}, + on_punch = function(pos, node, puncher, pointed_thing) + aliveai_electric.hit(puncher,15) + end, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" or pointed_thing.type=="nothing" then return itemstack end + local pvp=minetest.setting_getbool("enable_pvp") + local ob=pointed_thing.ref + if ob:is_player() and pvp==false then return itemstack end + aliveai_electric.hit(pointed_thing.ref,15) + itemstack:take_item(1) + return itemstack + end, +}) + +minetest.register_node("aliveai_threats:crystal_small", { + description = "Small crystal", + drawtype = "mesh", + mesh = "aliveai_threats_crystal.obj", + visual_scale = 2, + wield_scale = {x=2, y=2, z=2}, + alpha = 20, + tiles = { + { + name = "aliveai_threats_crystals.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + paramtype = "light", + paramtype2 = "facedir", + sunlight_propagates = true, + damage_per_second = 5, + walkable = false, + is_ground_content = false, + light_source=8, + selection_box = { + type = "fixed", + fixed = {-0.1, -0.5, -0.1, 0.1, 0.25, 0.1} + }, + groups = {cracky = 1, level = 1}, + on_punch = function(pos, node, puncher, pointed_thing) + aliveai_electric.hit(puncher,5) + end, + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" or pointed_thing.type=="nothing" then return itemstack end + local pvp=minetest.setting_getbool("enable_pvp") + local ob=pointed_thing.ref + if ob:is_player() and pvp==false then return itemstack end + aliveai_electric.hit(pointed_thing.ref,5) + itemstack:take_item(1) + return itemstack + end, +}) + +minetest.register_node("aliveai_threats:crystal_block", { + description = "Crystal block", + tiles = { + { + name = "aliveai_threats_crystals.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 2.0, + }, + }, + }, + groups = {cracky = 1, puts_out_fire = 1, not_in_creative_inventory=1}, + sounds = default.node_sound_stone_defaults(), + light_source=8, + paramtype = "light", + is_ground_content = false, + on_punch = function(pos, node, puncher, pointed_thing) + aliveai_electric.hit(pointed_thing.ref,5) + end, + +}) + +minetest.register_node("aliveai_threats:crystal_soil", { + description = "Crystal soil", + tiles = {"default_obsidian.png^[colorize:#6d1d7caa"}, + groups = { oddly_breakable_by_hand = 1,choppy = 1, not_in_creative_inventory=1}, + sounds = default.node_sound_dirt_defaults(), + light_source=5, + paramtype = "light", + is_ground_content = false, + on_punch = function(pos, node, puncher, pointed_thing) + aliveai_electric.hit(pointed_thing.ref,5) + end, +}) + +minetest.register_node("aliveai_threats:crystal_grass", { + description = "Crystal grass", + tiles = {"aliveai_threats_crystal_grass.png"}, + groups = {cracky = 2, puts_out_fire = 1, not_in_creative_inventory=1}, + sounds = default.node_sound_glass_defaults(), + paramtype = "light", + walkable = false, + sunlight_propagates = true, + drawtype = "plantlike", + damage_per_second = 3, +}) \ No newline at end of file diff --git a/aliveai_threats/depends.txt b/aliveai_threats/depends.txt new file mode 100644 index 0000000..cf96887 --- /dev/null +++ b/aliveai_threats/depends.txt @@ -0,0 +1,5 @@ +default +aliveai +nitroglycerine? +vessels? +aliveai_electric? \ No newline at end of file diff --git a/aliveai_threats/eyes.lua b/aliveai_threats/eyes.lua new file mode 100644 index 0000000..41749ff --- /dev/null +++ b/aliveai_threats/eyes.lua @@ -0,0 +1,252 @@ +aliveai_threats_eyes={active={}} + + +if aliveai.spawning then +minetest.register_abm({ + nodenames = {"group:tree"}, + interval = 30, + chance = 300, + action = function(pos) + aliveai_threats_eyes.spawn(pos) + end, +}) +end +aliveai_threats_eyes.checkspace=function(pos) + for i=1,4,1 do + local p1=minetest.get_node({x=pos.x+i,y=pos.y,z=pos.z}).name=="air" + local p2=minetest.get_node({x=pos.x-i,y=pos.y,z=pos.z}).name=="air" + local p3=minetest.get_node({x=pos.x,y=pos.y,z=pos.z+i}).name=="air" + local p4=minetest.get_node({x=pos.x,y=pos.y,z=pos.z-i}).name=="air" + if not (p1 and p2 and p3 and p4) then + return false + end + end + return true +end + +aliveai_threats_eyes.spawn=function(pos) + for i,v in pairs(aliveai_threats_eyes.active) do + if not v:get_luaentity() or v:get_hp()<1 then + table.remove(aliveai_threats_eyes.active,i) + elseif pos.x==v:get_luaentity().stat.x and pos.z==v:get_luaentity().stat.z then + return false + end + end + local pos1={x=pos.x,y=pos.y-1,z=pos.z} + local pos2={x=pos.x,y=pos.y+1,z=pos.z} + if minetest.get_item_group(minetest.get_node(pos).name,"tree")~=0 and + aliveai_threats_eyes.checkspace(pos) then + local p={ + {x=pos.x+1,y=pos.y,z=pos.z}, + {x=pos.x-1,y=pos.y,z=pos.z}, + {x=pos.x,y=pos.y,z=pos.z+1}, + {x=pos.x,y=pos.y,z=pos.z-1} + } + local side=math.random(1,4) + local ob=minetest.add_entity(p[side], "aliveai_threats:eyes") + ob:get_luaentity().side=side + ob:get_luaentity().stat=pos + return true + end + return false + +end + +aliveai_threats_eyes.sweating=function(self,pos) + local p1={x=pos.x,y=pos.y+0.3,z=pos.z} + local p2={x=pos.x,y=pos.y-0.3,z=pos.z} + if self.side==1 or self.side==2 then + p1.z=p1.z+0.3 + p2.z=p2.z-0.3 + else + p1.x=p1.x+0.3 + p2.x=p2.x-0.3 + end + minetest.add_particlespawner({ + amount = 1, + time =0.1, + maxpos = p1, + minpos = p2, + minvel = {x=0, y=-8, z=0}, + maxvel = {x=0, y=-8, z=0}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 0.3, + maxexptime = 0.3, + minsize = 0.5, + maxsize = 0.1, + texture = "default_water.png", + }) +end + +aliveai_threats_eyes.shoot=function(self) + if not (self.fight and math.random(1,20)==1) then return end + local e=minetest.add_item(aliveai.pointat(self,1),"default:stick") + local dir=aliveai.get_dir(self,self.fight) + local vc = {x = dir.x*30, y = dir.y*30, z = dir.z*30} + if not (vc and vc.x and vc.y and vc.z) or vc.x==math.huge or vc.x~=vc.x then return end + e:setvelocity(vc) + e:get_luaentity().age=(tonumber(minetest.setting_get("item_entity_ttl")) or 900)-2 + table.insert(aliveai_threats.debris,{ob=e,n=self.botname}) +end + +minetest.register_craftitem("aliveai_threats:tree_eyes", { + description = "Tree eyes spawner", + inventory_image = "aliveai_threats_eyes.png", + on_place = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" and aliveai_threats_eyes.spawn(pointed_thing.under) then + itemstack:take_item() + end + return itemstack + end +}) + +minetest.register_entity("aliveai_threats:eyes",{ + hp_max = 10, + physical =false, + weight = 0, + collisionbox = {0,0,0,0,0,0}, + visual = "upright_sprite", + visual_size = {x=1,y=1}, + textures ={"aliveai_threats_eyes.png"}, + colors = {}, + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, + on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir) + local en=puncher:get_luaentity() + if not self.exp and tool_capabilities and tool_capabilities.damage_groups and tool_capabilities.damage_groups.fleshy then + self.hp=self.hp-tool_capabilities.damage_groups.fleshy + self.object:set_hp(self.hp) + end + end, + get_staticdata = function(self) + return aliveai.convertdata({side=self.side,opos=self.opos,stat=self.stat}) + end, + on_activate=function(self, staticdata) + self.hp=self.object:get_hp() + local r=aliveai.convertdata(staticdata) + if r and r~="" then + self.side=r.side + self.opos=r.opos + self.stat=r.stat + end + self.botname=aliveai.genname() + self.opos=aliveai.roundpos(self.object:get_pos()) + + minetest.after(0.1, function(self) + if not self.stat then self.stat=self.object:get_pos() end + local s=3.14 + if not self.side then self.side=1 end + if self.side==1 then + s=4.71 + elseif self.side==2 then + s=1.57 + elseif self.side==3 then + s=0 + end + self.object:setyaw(s) + table.insert(aliveai_threats_eyes.active,self.object) + if self.side==1 then + self.opos.x=self.opos.x-0.49 + elseif self.side==2 then + self.opos.x=self.opos.x+0.49 + elseif self.side==3 then + self.opos.z=self.opos.z-0.49 + elseif self.side==4 then + self.opos.z=self.opos.z+0.49 + end + self.object:set_pos(self.opos) + end,self) + return self + end, + on_step=function(self, dtime) + self.time=self.time+dtime + self.time2=self.time2+dtime + if self.time0.3 then z=0.3 end + if z<-0.3 then z=-0.3 end + else + x=(obpos.x-self.opos.x)/d + if x>0.3 then x=0.3 end + if x<-0.3 then x=-0.3 end + end + y=(obpos.y-self.opos.y)/d + if y>0.3 then y=0.3 end + if y<-0.3 then y=-0.3 end + local spos=false + if self.lookat then spos=aliveai.samepos(self.lookat,obpos) end + self.object:moveto({x=self.opos.x+x,y=self.opos.y+y,z=self.opos.z+z}) + self.lookat=obpos + self.timer=0.1 + + if self.fight then + aliveai_threats_eyes.shoot(self) + end + + if not self.fight and spos and self.time2>10 then + if d<4 then + aliveai_threats_eyes.sweating(self,pos) + else + self.object:set_properties({textures = {"aliveai_threats_eyes_mad.png"}}) + self.fight=ob + self.time2=0 + self.type="monster" + end + elseif self.fight and self.time2>20 then + self.object:moveto(self.opos) + self.timer=2 + self.time2=0 + self.fight=nil + self.lookat=nil + self.object:moveto(self.opos) + self.object:set_properties({textures = {"aliveai_threats_eyes.png"}}) + self.type="" + elseif not spos then + self.time2=0 + end + return self + end, + time=0, + timer=2, + time2=0, + type="", + team="tree", + aliveai_eyes=1, +}) +aliveai.loaded("aliveai_threats:eyes") diff --git a/aliveai_threats/flowerattack.lua b/aliveai_threats/flowerattack.lua new file mode 100644 index 0000000..b9bf836 --- /dev/null +++ b/aliveai_threats/flowerattack.lua @@ -0,0 +1,77 @@ +aliveai.create_bot({ + attack_players=1, + name="flower", + team="flowers", + texture="flowers_rose.png", + talking=0, + light=0, + building=0, + type="monster", + hp=1, + dmg=1, + arm=1, + name_color="", + collisionbox={-0.1,-0.5,-0.1,0.1,0.2,0.1}, + visual="cube", + drop_dead_body=0, + escape=0, + spawn_on={"group:flora"}, + attack_chance=1, + spawn_chance=50, + --spawn_interval=5, + spawn_y=-1, + smartfight=0, + basey=-1, + spawn=function(self,t,t2) + if not self.storge2 then + local pos=self.object:get_pos() + if aliveai.group(pos,"flora")==0 or minetest.is_protected(pos,"") then + aliveai.kill(self) + return self + end + self.storge1=minetest.get_node(pos).name + self.inv[self.storge1]=1 + minetest.remove_node(pos) + pos={x=pos.x,y=pos.y+1,z=pos.z} + self.object:set_pos(pos) + end + self.object:set_properties({visual="wielditem",visual_size={x=0.5,y=0.5},textures={self.storge1}}) + end, + on_load=function(self) + self.spawn(self) + end, + on_step=function(self,dtime) + if self.fight and not self.storge2 then + local nodes=aliveai.get_nodes(self,self.distance,1) + for _, nodepos in ipairs(nodes) do + if aliveai.group(nodepos,"flora")>0 then + local f=minetest.add_entity(nodepos, "aliveai_threats:flower") + f:setyaw(math.random(0,6.28)) + local en=f:get_luaentity() + aliveai.known(en,self.fight,"fight") + en.folow=self.fight + en.fight=self.fight + en.temper=10 + en.storge2=1 + aliveai.folowing(en) + return + end + end + elseif not self.fight and self.storge2 and aliveai.def(self.object:get_pos(),"buildable_to") then + if minetest.get_node(self.object:get_pos()).name~="air" then return end + local pos=self.object:get_pos() + if minetest.is_protected(pos,"") then + aliveai.kill(self) + else + minetest.set_node(pos,{name=self.storge1}) + self.object:remove() + end + end + end, + death=function(self,puncher,pos) + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + aliveai.lookat(self,pos) + end +}) \ No newline at end of file diff --git a/aliveai_threats/fort.lua b/aliveai_threats/fort.lua new file mode 100644 index 0000000..27fc7cd --- /dev/null +++ b/aliveai_threats/fort.lua @@ -0,0 +1,207 @@ +aliveai_threats.fort={furnishings={"aliveai_threats:toxic_tank","aliveai_threats:labbottle_containing","aliveai_threats:timed_bumb","aliveai_threats:timed_nitrobumb","aliveai_threat_eletric:timed_ebumb","aliveai_threats:landmine","aliveai_threats:deadlock","aliveai_massdestruction:nuclearbarrel"},} + +minetest.register_tool("aliveai_threats:fortspawner", { + description = "fort spawner", + range=15, + groups={not_in_creative_inventory=1}, + inventory_image = "default_stick.png", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" then + aliveai_threats.fort.spawning(pointed_thing.under,1) + end + end, +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "aliveai_threats:fort_spawner", + wherein = "default:dirt_with_grass", + clust_scarcity = 20 * 20 * 20, + clust_num_ores = 1, + clust_size = 1, + y_min = -1, + y_max = 50, +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "aliveai_threats:fort_spawner", + wherein = "default:snow", + clust_scarcity = 20 * 20 * 20, + clust_num_ores = 1, + clust_size = 1, + y_min = -1, + y_max = 50, +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "aliveai_threats:fort_spawner", + wherein = "default:snowblock", + clust_scarcity = 20 * 20 * 20, + clust_num_ores = 1, + clust_size = 1, + y_min = -1, + y_max = 50, +}) + +minetest.register_abm({ + nodenames = {"aliveai_threats:fort_spawner"}, + interval = 10, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + minetest.set_node(pos,{name="default:stone"}) + aliveai_threats.fort.spawning(pos) + end +}) + +aliveai_threats.fort.spawning=function(pos,nrnd) + if not nrnd and math.random(1,20)~=1 then return end + local test1=0 + local test2=0 + + for y=-5,6,1 do + for x=-5,31,1 do + for z=-5,31,1 do + local p={x=pos.x+x,y=pos.y+y,z=pos.z+z} + if nrnd and minetest.is_protected(p,"") then return end + if y<1 and aliveai.def(p,"walkable") then + test1=test1+1 + elseif y>0 and aliveai.def(p,"walkable") then + test2=test2+1 + + if test2>3000 then return end + end + end + end + end + + if test1<7000 then return end + + local door=math.random(11,17) + local n + local cam + local start + for y=0,6,1 do + for x=-5,31,1 do + for z=-5,31,1 do + local p={x=pos.x+x,y=pos.y+y,z=pos.z+z} + local n="air" + local param=0 + if y==0 then + n="default:silver_sandstone_brick" + elseif y==6 and ((x==9 and z==9) or (x==18 and z==18) or (x==18 and z==9) or (x==9 and z==18)) then + n="aliveai_threats:secam2" + cam=1 + elseif y<5 and (x==1 or x==26 or z==1 or z==26) and (x>0 and z>0 and x<27 and z<27) then + n="aliveai_threats:chainfence" + if aliveai_electric then start=1 end + param=1 + if x==1 then + param=1 + elseif x==26 then + param=3 + elseif z==1 then + param=2 + else + param=0 + end + elseif (y==1 or y==2) and (((x==door and (z==9 or z==18)) or (z==door and (x==9 or x==18))))then + if y==1 then n="aliveai:door_steel" end + elseif (y==1 or y==2) and (x==door or z==door) then + elseif (y==1 or y==2) and (((x==10 or x==17) and (z>9 and z<18)) or ((z==10 or z==17) and (x>9 and x<18))) then + if y==1 then + n="aliveai_threats:labtable" + elseif math.random(1,3)==1 then + n=aliveai_threats.fort.furnishings[math.random(1,#aliveai_threats.fort.furnishings)] + end + elseif y<5 and (((x==9 or x==18) and (z>8 and z<19)) or ((z==9 or z==18) and (x>8 and x<19))) then + n="default:silver_sandstone_brick" + elseif y==5 and (x>8 and x<19 and z>8 and z<19) then + n="default:silver_sandstone_brick" + end + + if n then + minetest.set_node(p,{name=n,param2=param}) + if cam then + minetest.get_meta(p):set_string("team","nuke") + minetest.get_node_timer(p):start(1) + cam=nil + elseif start then + minetest.get_node_timer(p):start(1) + start=nil + end + end + end + end + end + + if math.random(1,3)==1 then return end + + for y=-5,0,1 do + for x=-4,30,1 do + for z=-4,30,1 do + local p={x=pos.x+x,y=pos.y+y,z=pos.z+z} + local n=nil + if y==-5 and ((x<0 or x>26) or (z<0 or z>26)) then + n="default:silver_sandstone_brick" + elseif x==-4 or x==30 or z==-4 or z==30 then + n="default:silver_sandstone_brick" + elseif (x>-4 and x<0) or (x>26 and x<30) or (z>-5 and z<0) or (z>26 and z<30) then + n="aliveai_threats:slime" + elseif x==0 or x==26 or z==0 or z==26 then + n="default:silver_sandstone_brick" + end + + if n then + minetest.set_node(p,{name=n}) + end + end + end + end +end + +minetest.register_node("aliveai_threats:fort_spawner", { + tiles={"default_stone.png"}, + groups = {not_in_creative_inventory=1}, + is_ground_content = false +}) + + +minetest.register_node("aliveai_threats:chainfence", { + description = "Chain fence", + tiles = {"aliveai_threats_chainfence.png"}, + drawtype = "nodebox", + groups = {cracky=1, not_in_creative_inventory=0,level=3}, + sounds = default.node_sound_stone_defaults(), + 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}}, + on_punch = function(pos, node, puncher, pointed_thing) + if not (puncher:is_player() and minetest.get_meta(pos):get_string("owner")==puncher:get_player_name()) then + if aliveai_electric and aliveai.team(puncher)~="nuke" then + aliveai_electric.hit(puncher,20,5) + end + end + end, + after_place_node = function(pos, placer) + if placer:is_player() then + minetest.get_meta(pos):set_string("owner",placer:get_player_name()) + end + end, + on_construct = function(pos) + if aliveai_electric then + minetest.get_node_timer(pos):start(5) + end + end, + on_timer = function (pos, elapsed) + if math.random(1,4)~=1 then return true end + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + if aliveai.team(ob)~="nuke" then + aliveai_electric.hit(ob,20,5) + end + end + return true + end +}) \ No newline at end of file diff --git a/aliveai_threats/init.lua b/aliveai_threats/init.lua new file mode 100644 index 0000000..78112fe --- /dev/null +++ b/aliveai_threats/init.lua @@ -0,0 +1,2921 @@ +aliveai_threats={c4={},debris={},n=0,tox_obs={},stopacidplayer={}} + +dofile(minetest.get_modpath("aliveai_threats") .. "/eyes.lua") +dofile(minetest.get_modpath("aliveai_threats") .. "/sec.lua") +dofile(minetest.get_modpath("aliveai_threats") .. "/lab.lua") +dofile(minetest.get_modpath("aliveai_threats") .. "/flowerattack.lua") +dofile(minetest.get_modpath("aliveai_threats") .. "/crystal.lua") +dofile(minetest.get_modpath("aliveai_threats") .. "/tree.lua") +dofile(minetest.get_modpath("aliveai_threats") .. "/fort.lua") + +aliveai.savedata.clone=function(self) + if self.clone then + return {clone=1} + end + if self.natural_monster then + return {t1=self.t1,t2=self.t2,t3=self.t3,natural_monster=1,consists=self.consists} + end + + if self.killed and self.body then + return {body=self.body,killed=self.killed,hp_max=self.hp_max} + end + + +end + +aliveai.loaddata.clone=function(self,r) + if r.clone then + self.clone=r.clone + end + if r.natural_monster then + self.t1=r.t1 + self.t2=r.t2 + self.t3=r.t3 + self.natural_monster=1 + self.consists=r.consists + end + if r.killed and r.body then + self.body=r.body + self.killed=1 + self.hp_max=r.hp_max + end + return self +end + + + + + +aliveai_threats.tox=function(ob) + + if not ob or not ob:get_pos() or aliveai.gethp(ob,1)<1 or aliveai.team(ob)=="nuke" then + if ob and ob:is_player() then + if aliveai_threats.tox_obs[ob:get_player_name()]==2 then return end + aliveai_threats.tox_obs[ob:get_player_name()]=nil + end + return + end + if ob:is_player() then + if aliveai_threats.tox_obs[ob:get_player_name()]==2 then return end + aliveai_threats.tox_obs[ob:get_player_name()]=1 + elseif ob:get_luaentity() then + ob:get_luaentity().aliveai_threats_tox=1 + end + + local pos=ob:get_pos() + for _, obs in ipairs(minetest.get_objects_inside_radius(pos, 4)) do + if aliveai.visiable(pos,obs:get_pos()) and not ((ob:get_luaentity() and ob:get_luaentity().aliveai_threats_tox) or (ob:is_player() and aliveai_threats.tox_obs[ob:get_player_name()])) then aliveai_threats.tox(obs) end + end + aliveai.punchdmg(ob) + if aliveai.gethp(ob,1)<1 or math.random(1,40)==1 then + if ob and ob:is_player() then + local name=ob:get_player_name() + aliveai_threats.tox_obs[name]=2 + minetest.after(5, function(name) + aliveai_threats.tox_obs[name]=nil + end,name) + elseif ob:get_luaentity() then + ob:get_luaentity().aliveai_threats_tox=nil + end + return + end + + minetest.after(math.random(1,2), function(ob) + aliveai_threats.tox(ob) + end,ob) +end +aliveai.create_bot({ + attack_players=1, + name="toxic_gassman", + team="nuke", + texture="aliveai_threats_gassman.png^[colorize:#00ff0055", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + type="monster", + dmg=0, + hp=100, + name_color="", + arm=2, + coming=0, + smartfight=0, + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","default:stone"}, + attack_chance=5, + on_punching=function(self,target) + aliveai_threats.tox(target) + end, + on_blow=function(self) + aliveai.kill(self) + self.death(self,self.object,self.object:getpos()) + end, + death=function(self,puncher,pos) + if not self.ex then + self.ex=true + aliveai_nitroglycerine.explode(pos,{ + radius=1, + set="air", + blow_nodes=0, + hurt=0 + }) + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 4)) do + if aliveai.visiable(pos,ob:get_pos()) then aliveai_threats.tox(ob,1) end + end + end + return self + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + aliveai_threats.tox(puncher) + minetest.add_particlespawner({ + amount = 5, + time=0.2, + minpos = pos, + maxpos = pos, + minvel = {x=-0.1, y=-0.1, z=-0.1}, + maxvel = {x=0.1, y=0.1, z=0.1}, + minacc = {x=0, y=0, z=0}, + maxacc = {x=0, y=0, z=0}, + minexptime = 0.5, + maxexptime = 1, + minsize = 0.5, + maxsize = 2, + texture = "default_grass.png^[colorize:#00ff0055", + }) + end +}) + + + +if minetest.get_modpath("aliveai_nitroglycerine")~=nil then + +minetest.register_craft({ + output = "aliveai_threats:c4 2", + recipe = { + {"default:steel_ingot","default:coal_lump","default:steel_ingot"}, + {"default:steel_ingot","default:mese_crystal_fragment","default:steel_ingot"}, + {"default:steel_ingot","default:copper_ingot","default:steel_ingot"}, + } +}) + + +minetest.register_craftitem("aliveai_threats:c4", { + description = "C4 bomb", + inventory_image = "aliveai_threats_c4.png", + on_use = function(itemstack, user, pointed_thing) + local name=user:get_player_name() + local c=aliveai_threats.c4[name] + if not c and pointed_thing.type=="object" then + local ob=pointed_thing.ref + aliveai_threats.c4[user:get_player_name()]=ob + user:get_inventory():add_item("main","aliveai_threats:c4_controler") + itemstack:take_item() + elseif not c then + aliveai_threats.c4[name]=nil + end + return itemstack + end +}) + +minetest.register_craftitem("aliveai_threats:c4_controler", { + description = "C4 controller", + inventory_image = "aliveai_threats_c4_controller.png", + groups = {not_in_creative_inventory=1}, + on_use = function(itemstack, user, pointed_thing) + local name=user:get_player_name() + local ob=aliveai_threats.c4[name] + if ob and ob:get_pos() and ob:get_pos().x then + local pos=ob:get_pos() + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 3)) do + local en=ob:get_luaentity() + if en and en.aliveai then en.drop_dead_body=0 end + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=200}}) + end + aliveai_nitroglycerine.explode(pos,{ + radius=3, + set="air", + }) + else + user:get_inventory():add_item("main","aliveai_threats:c4") + end + aliveai_threats.c4[name]=nil + itemstack:take_item() + return itemstack + end +}) + + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="nitrogen", + team="ice", + texture="aliveai_threats_nitrogen.png", + stealing=1, + steal_chanse=2, + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["default:snowblock"]=1,["default:ice"]=4}, + type="monster", + dmg=1, + hp=40, + name_color="", + arm=2, + spawn_on={"default:silver_sand","default:dirt_with_snow","default:snow","default:snowblock","default:ice"}, + on_step=function(self,dtime) + local pos=self.object:get_pos() + pos.y=pos.y-1.5 + local node=minetest.get_node(pos) + if node and node.name and minetest.is_protected(pos,"")==false then + if minetest.get_item_group(node.name, "soil")>0 then + minetest.set_node(pos,{name="default:dirt_with_snow"}) + elseif minetest.get_item_group(node.name, "sand")>0 and minetest.registered_nodes["default:silver_sand"] then + minetest.set_node(pos,{name="default:silver_sand"}) + elseif minetest.get_item_group(node.name, "water")>0 then + minetest.set_node(pos,{name="default:ice"}) + pos.y=pos.y+1 + if minetest.get_item_group(minetest.get_node(pos).name, "water")>1 then + minetest.set_node(pos,{name="default:ice"}) + end + elseif minetest.get_item_group(node.name, "lava")>0 then + minetest.set_node(pos,{name="default:ice"}) + pos.y=pos.y+1 + if minetest.get_item_group(minetest.get_node(pos).name, "lava")>1 then + minetest.set_node(pos,{name="default:ice"}) + end + end + end + end, + on_punching=function(self,target) + if aliveai.gethp(target)<=self.dmg+5 then + aliveai_nitroglycerine.freeze(target) + else + target:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=self.dmg}},nil) + end + end, + death=function(self,puncher,pos) + minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 5,}) + aliveai_nitroglycerine.crush(pos) + end, +}) + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="gassman", + team="nuke", + texture="aliveai_threats_gassman.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + type="monster", + dmg=0, + hp=100, + name_color="", + arm=2, + coming=0, + smartfight=0, + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","group:stone"}, + attack_chance=5, + on_fighting=function(self,target) + if not self.ti then self.ti={t=1,s=0} end + self.temper=10 + self.ti.s=self.ti.s-1 + if self.ti.s<=0 then + self.ti.t=self.ti.t-1 + if self.ti.t>=0 then + self.ti.s=99 + end + end + if self.ti.t<0 then + local pos=self.object:get_pos() + self.ex=true + aliveai.kill(self) + aliveai_nitroglycerine.explode(pos,{ + radius=10, + set="air", + drops=0, + }) + return self + end + + local tag=self.ti.t ..":" .. self.ti.s + self.object:set_properties({nametag=tag,nametag_color="#ff0000aa"}) + end, + on_blow=function(self) + aliveai.kill(self) + self.death(self,self.object,self.object:getpos()) + end, + death=function(self,puncher,pos) + if not self.ex then + self.hp=0 + self.ex=true + aliveai_nitroglycerine.explode(pos,{ + radius=2, + set="air", + }) + end + return self + end, +}) + + + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="nitrogenblow", + team="ice", + texture="aliveai_threats_nitrogenblow.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["default:snowblock"]=10,["default:ice"]=2}, + spawn_on={"default:silver_sand","default:dirt_with_snow","default:snow","default:snowblock","default:ice"}, + type="monster", + dmg=1, + hp=30, + name_color="", + arm=2, + coming=0, + smartfight=0, + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","group:stone"}, + attack_chance=5, + on_fighting=function(self,target) + if aliveai.gethp(target)<=self.dmg+5 then + aliveai_nitroglycerine.freeze(target) + elseif math.random(1,10)==1 then + target:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=self.dmg}},nil) + end + if not self.ti then self.ti={t=5,s=9} end + self.temper=10 + self.ti.s=self.ti.s-1 + if self.ti.s<=0 then + self.ti.t=self.ti.t-1 + if self.ti.t>=0 then + self.ti.s=9 + end + end + if self.ti.t<0 then + self.ex=true + if aliveai.gethp(target)<=11 then + aliveai_nitroglycerine.freeze(target) + else + target:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=10}},nil) + end + aliveai_nitroglycerine.crush(self.object:get_pos()) + aliveai.kill(self) + return self + end + local tag=self.ti.t ..":" .. self.ti.s + self.object:set_properties({nametag=tag,nametag_color="#ff0000aa"}) + end, + death=function(self,puncher,pos) + minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 5,}) + if not self.ex then + self.ex=true + self.aliveai_ice=1 + local radius=10 + aliveai_nitroglycerine.explode(pos,{ + radius=radius, + hurt=0, + place={"default:snowblock","default:ice","default:snowblock"}, + place_chance=2, + }) + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, radius*2)) do + local pos2=ob:get_pos() + local d=math.max(1,vector.distance(pos,pos2)) + local dmg=(8/d)*radius + local en=ob:get_luaentity() + if ob:is_player() or not (en and en.name=="aliveai_nitroglycerine:ice" or en.aliveai_ice) then + if ob:get_hp()<=dmg+5 then + aliveai_nitroglycerine.freeze(ob) + else + ob:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=dmg}}) + end + end + end + end + return self + end, +}) + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="heavygassman", + team="nuke", + texture="aliveai_threats_gassman2.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["default:coal_lump"]=4}, + type="monster", + dmg=0, + hp=20, + name_color="", + arm=2, + coming=1, + smartfight=0, + attack_chance=1, + on_fighting=function(self,target) + if not self.t then self.t=20 end + self.temper=10 + self.t=self.t-1 + if self.t<0 then + aliveai.kill(self) + return self + end + self.object:set_properties({nametag=self.t,nametag_color="#ff0000aa"}) + end, + on_blow=function(self) + aliveai.kill(self) + self.death(self,self.object,self.object:getpos()) + end, + death=function(self,puncher,pos) + if not self.ex then + self.ex=true + local radius=10 + aliveai_nitroglycerine.explode(pos,{ + radius=radius, + place={"aliveai_threats:gass","aliveai_threats:gass"}, + set="aliveai_threats:gass", + place_chance=1, + }) + end + return self + end, +}) + +minetest.register_node("aliveai_threats:gass", { + description = "Gass", + inventory_image = "bubble.png", + tiles = {"aliveai_air.png"}, + walkable = false, + pointable = false, + drowning = 1, + buildable_to = true, + drawtype = "glasslike", + post_effect_color = {a = 248, r =0, g = 0, b = 0}, + damage_per_second = 1, + paramtype = "light", + liquid_viscosity = 15, + liquidtype = "source", + liquid_range = 0, + liquid_alternative_flowing = "aliveai_threats:gass", + liquid_alternative_source = "aliveai_threats:gass", + groups = {liquid = 4,crumbly = 1,not_in_creative_inventory=1} +}) + +if minetest.get_modpath("fire")~=nil then + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="lava", + team="lava", + texture="default_lava.png", + attacking=1, + talking=0, + light=0, + building=0, + start_with_items={["default:obsidian"]=1,["default:obsidian_shard"]=3}, + type="monster", + hp=50, + dmg=8, + escape=0, + name_color="", + attack_chance=2, + damage_by_blocks=0, + spawn_on={"default:lava_source","default:lava_flowing"}, + spawn_in="default:lava_source", + on_load=function(self) + self.hp2=self.object:get_hp() + end, + on_step=function(self,dtime) + if (self.fight and math.random(1,3)==1) or math.random(1,10)==1 then + local pos=self.object:get_pos() + for y=-2,4,1 do + for x=-2,4,1 do + for z=-2,4,1 do + local p1={x=pos.x+x,y=pos.y+y,z=pos.z+z} + local p2={x=pos.x+x,y=pos.y+y-1,z=pos.z+z} + local no1=minetest.get_node(p1).name + local no2=minetest.get_node(p2).name + if not (minetest.registered_nodes[no1] and minetest.registered_nodes[no2]) then return end + if minetest.get_item_group(no1, "igniter")==0 and minetest.registered_nodes[no1].buildable_to and minetest.registered_nodes[no2].walkable and aliveai.visiable(pos,p1) then + minetest.set_node(p1, {name = "fire:basic_flame"}) + end + end + end + end + end + end, + on_punched=function(self,puncher) + if self.hp2 and self.hp2-self.object:get_hp()<5 then + self.object:set_hp(self.hp2) + return self + end + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "default_lava.png", + collisiondetection = true, + }) + end, + death=function(self,puncher,pos) + if not self.ex then + self.ex=true + aliveai_nitroglycerine.explode(pos,{ + radius=7, + place={"fire:basic_flame","fire:basic_flame"}, + }) + end + return self + end, +}) + + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="fire", + team="lava", + texture="fire_basic_flame.png", + attacking=1, + talking=0, + light=0, + building=0, + start_with_items={["default:obsidian"]=1,["default:obsidian_shard"]=3}, + type="monster", + hp=30, + name_color="", + attack_chance=2, + damage_by_blocks=0, + spawn_on={"fire:basic_flame"}, + dmg=5, + escape=0, + on_load=function(self) + self.hp2=self.object:get_hp() + end, + on_step=function(self,dtime) + if (self.fight and math.random(1,3)==1) or math.random(1,10)==1 then + local pos=self.object:get_pos() + for y=-1,1,1 do + for x=-1,1,1 do + for z=-1,1,1 do + local p1={x=pos.x+x,y=pos.y+y,z=pos.z+z} + local p2={x=pos.x+x,y=pos.y+y-1,z=pos.z+z} + local no1=minetest.get_node(p1).name + local no2=minetest.get_node(p2).name + if not (minetest.registered_nodes[no1] and minetest.registered_nodes[no2]) then return end + if minetest.get_item_group(no1, "igniter")==0 and minetest.registered_nodes[no1].buildable_to and minetest.registered_nodes[no2].walkable and aliveai.visiable(pos,p1) then + minetest.set_node(p1, {name = "fire:basic_flame"}) + end + end + end + end + end + end, + on_punched=function(self,puncher) + if self.hp2 and self.hp2-self.object:get_hp()<5 then + self.object:set_hp(self.hp2) + return self + end + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "fire_basic_flame.png", + collisiondetection = true, + }) + end, + death=function(self,puncher,pos) + if not self.ex then + self.ex=true + aliveai_nitroglycerine.explode(pos,{ + radius=5, + place={"fire:basic_flame","fire:basic_flame"}, + }) + end + return self + end, +}) +end + + + + + +end + +aliveai.create_bot({ + attack_players=1, + name="terminator", + team="nuke", + texture="aliveai_threats_terminator.png", + attacking=1, + talking=0, + --light=0, + building=0, + escape=0, + start_with_items={["default:steel_ingot"]=4,["default:steelblock"]=1}, + type="monster", + dmg=0, + hp=200, + arm=3, + name_color="", + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","group:stone"}, + attack_chance=5, + on_punching=function(self,target) + local pos=self.object:get_pos() + pos.y=pos.y-0.5 + local radius=self.arm + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, radius)) do + local pos2=ob:get_pos() + local d=math.max(1,vector.distance(pos,pos2)) + local dmg=(8/d)*radius + local en=ob:get_luaentity() + if ob:is_player() or not (en and en.team==self.team or ob.itemstring) then + if en and en.object then + if en.type~="" then ob:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=dmg}},nil) end + dmg=dmg*2 + ob:setvelocity({x=(pos2.x-pos.x)*dmg, y=((pos2.y-pos.y)*dmg)+2, z=(pos2.z-pos.z)*dmg}) + elseif ob:is_player() then + ob:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=dmg}},nil) + local d=dmg/2 + local v=0 + local dd=0 + local p2={x=pos.x-pos2.x, y=pos.y-pos2.y, z=pos.z-pos2.z} + local tmp + for i=0,10,1 do + dd=d*v + tmp={x=pos.x+(p2.x*dd), y=pos.y+(p2.y*dd)+2, z=pos.z+(p2.z*dd)} + local n=minetest.get_node(tmp) + if n and n.name and minetest.registered_nodes[n.name].walkable then + if minetest.is_protected(tmp,"")==false and minetest.dig_node(tmp) then + for _, item in pairs(minetest.get_node_drops(n.name, "")) do + if item then + local it=minetest.add_item(tmp, item) + it:get_luaentity().age=890 + it:setvelocity({x = math.random(-1, 1),y=math.random(-1, 1),z = math.random(-1, 1)}) + end + end + else + break + end + end + v=v-0.1 + end + d=d*v + ob:set_pos({x=pos.x+(p2.x*d), y=pos.y+(p2.y*d)+2, z=pos.z+(p2.z*d)}) + end + end + end + end, + on_load=function(self) + self.hp2=self.object:get_hp() + end, + spawn=function(self) + self.hp2=self.object:get_hp() + end, + on_punched=function(self,puncher) + if self.hp2 and self.hp2-self.object:get_hp()<5 then + self.object:set_hp(self.hp2) + return self + end + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "default_steel_block.png", + collisiondetection = true, + spawn_chance=100, + }) + end +}) + + + +aliveai.create_bot({ + attack_players=1, + name="pull_monster", + team="pull", + texture="aliveai_threats_pull.png", + visual_size={x=0.8,y=1.4}, + collisionbox={-0.33,-1.3,-0.33,0.33,1.5,0.33}, + attacking=1, + talking=0, + light=-1, + lowest_light=9, + building=0, + smartfight=0, + escape=0, + type="monster", + dmg=0, + hp=80, + arm=2, + name_color="", + spawn_on={"group:sand","group:spreading_dirt_type","group:stone","default:snow"}, + attack_chance=3, + spawn_chance=200, + spawn_y=1, + on_punching=function(self,target) + if not self.pull_down then + local pos=aliveai.roundpos(target:get_pos()) + local n=minetest.get_node(pos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable then return end + pos.y=pos.y-1 + self.pull_down={pos={pos0=pos}} + local p + for i=1,3,1 do + p={x=pos.x,y=pos.y-i,z=pos.z} + n=minetest.get_node(p) + self.pull_down.pos["pos" .. i]=p + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable==false then + self.pull_down=nil + return + end + end + self.pull_down.target=target + end + end, + on_detect_enemy=function(self,target) + self.object:set_properties({ + mesh = aliveai.character_model, + textures = {"aliveai_threats_pull.png"}, + }) + end, + on_load=function(self) + self.move.speed=0.5 + local pos=aliveai.roundpos(self.object:get_pos()) + local n=minetest.get_node(pos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable then + pos.y=pos.y+3 + local l=minetest.get_node_light(pos) + if not l then return end + local n=minetest.get_node(pos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable then + self.domovefromslp=true + return self + elseif l>9 then + self.sleep={ground=pos} + return self + else + self.domovefromslp=true + return self + end + end + end, + on_step=function(self,dtime) + if self.movefromslp then + aliveai.rndwalk(self,false) + aliveai.stand(self) + for i, v in pairs(self.movefromslp) do + self.object:moveto(v) + table.remove(self.movefromslp,i) + return self + end + self.movefromslp=nil + return self + end + if self.domovefromslp then + self.domovefromslp=nil + local pos=self.object:get_pos() + local gpos={x=pos.x,y=pos.y+3,z=pos.z} + local n=minetest.get_node(gpos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable then + self.movefromslp={} -- move up from stuck sleep pos + local p3=0 + for i=1,103,1 do + local p={x=gpos.x,y=gpos.y+i,z=gpos.z} + local n=minetest.get_node(p) + self.movefromslp[i]=p + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable==false then + p3=p3+1 + if p3>2 then + self.sleep=nil + return self + end + else + p3=0 + end + end + aliveai.kill(self) + return self + end + end + if self.sleep then + local pos=aliveai.roundpos(self.object:get_pos()) + if self.sleep.pos then + if self.sleep.pos.pos0 then + self.object:moveto(self.sleep.pos.pos0) + self.sleep.pos.pos0=nil + elseif self.sleep.pos.pos1 then + self.object:moveto(self.sleep.pos.pos1) + self.sleep.pos.pos1=nil + elseif self.sleep.pos.pos2 then + self.object:moveto(self.sleep.pos.pos2) + self.sleep.pos=nil + end + if not self.pull_down then return self end + end + if self.pull_down then + if self.pull_down.target and self.pull_down.pos then + if self.pull_down.pos.pos0 and not (self.sleep.pos and self.sleep.pos.pos2) then + self.pull_down=nil + self.sleep=nil + return + end + if self.pull_down.pos.pos0 then + self.pull_down.target:moveto(self.pull_down.pos.pos0) + self.pull_down.pos.pos0=nil + elseif self.pull_down.pos.pos1 then + self.pull_down.target:moveto(self.pull_down.pos.pos1) + self.pull_down.pos.pos1=nil + elseif self.pull_down.pos.pos2 then + self.pull_down.target:moveto(self.pull_down.pos.pos2) + self.pull_down.pos=nil + end + return self + end + if self.pull_down.target and aliveai.gethp(self.pull_down.target)>0 and aliveai.distance(self,self.pull_down.target:get_pos())<=self.arm+1 then + aliveai.punch(self,self.pull_down.target,1) + if aliveai.gethp(self.pull_down.target)<=0 then + self.object:set_hp(self.hp_max) + aliveai.showhp(self,true) + self.domovefromslp=true + end + return self + else + self.sleep=nil + self.pull_down=nil + return + end + end + if self.hide then + self.time=self.otime + if math.random(1,2)==1 then + if not self.abortsleep then + for _, ob in ipairs(minetest.get_objects_inside_radius(self.sleep.ground, 10)) do + local en=ob:get_luaentity() + if not (en and en.aliveai and en.team==self.team) then + return self + end + end + end + self.hide=nil + self.pull_down=nil + self.domovefromslp=true + end + if self.hide then return self end + end + local l=minetest.get_node_light(self.sleep.ground) + if not l then + aliveai.kill(self) + self.sleep=nil + self.domovefromslp=true + return self + elseif l<=9 or self.abortsleep then + self.domovefromslp=true + else + if math.random(1,10)==1 then + for _, ob in ipairs(minetest.get_objects_inside_radius(self.sleep.ground, self.distance)) do + local en=ob:get_luaentity() + if not (en and en.aliveai and en.team==self.team) then + return self + end + end + aliveai.kill(self) + end + return self + end + elseif math.random(1,10)==1 or self.pull_down or self.hide then + local pos=aliveai.roundpos(self.object:get_pos()) + pos.y=pos.y-1 + local l=minetest.get_node_light(pos) + if not l then return end + if l>9 or self.pull_down or self.hide then + local p + self.sleep={ground=pos,pos={pos0=pos}} + for i=1,3,1 do + p={x=pos.x,y=pos.y-i,z=pos.z} + local n=minetest.get_node(p) + self.sleep.pos["pos" .. i]=p + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable==false then + self.sleep=nil + self.pull_down=nil + return + end + end + aliveai.rndwalk(self,false) + aliveai.stand(self) + return self + end + elseif math.random(1,10)==1 then + local pos=self.object:get_pos() + pos.y=pos.y-1.5 + local n=minetest.get_node(pos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].tiles then + local tiles=minetest.registered_nodes[n.name].tiles + if type(tiles)=="table" and type(tiles[1])=="string" then + self.tex=tiles[1] + self.object:set_properties({ + mesh = aliveai.character_model, + textures = {tiles[1]}, + }) + end + end + end + end, + on_punched=function(self,puncher) + self.object:set_properties({ + mesh = aliveai.character_model, + textures = {"aliveai_threats_pull.png"}, + }) + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = self.tex or "default_dirt.png", + collisiondetection = true, + }) + self.tex=nil + if self.sleep or self.hide then self.abortsleep=true end + if self.hide or not self.fight then return end + if not self.ohp then self.ohp=self.object:get_hp()*0.8 return end + if self.ohp>self.object:get_hp() then + local pos=self.object:get_pos() + local n=minetest.get_node(pos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable then return end + self.hide=true + self.ohp=nil + self.time=0.2 + self.pull_down=nil + return self + end + end +}) + +minetest.register_craft({ + output = "aliveai_threats:mind_manipulator", + recipe = { + {"default:steel_ingot", "default:papyrus"}, + {"default:steel_ingot", "default:mese_crystal"}, + {"default:steel_ingot", "default:obsidian_glass"}, + } +}) + +minetest.register_tool("aliveai_threats:mind_manipulator", { + description = "Mind manipulator", + inventory_image = "aliveai_threats_mind_manipulator.png", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="object" then + local ob=pointed_thing.ref + if ob:get_luaentity() and ob:get_luaentity().type and ob:get_luaentity().type=="monster" then + ob:get_luaentity().team="mind_manipulator" .. math.random(1,100) + elseif ob:get_luaentity() then + ob:get_luaentity().type="monster" + ob:get_luaentity().team="mind_manipulator" .. math.random(1,100) + ob:get_luaentity().attack_players=1 + ob:get_luaentity().attacking=1 + ob:get_luaentity().talking=0 + ob:get_luaentity().light=0 + ob:get_luaentity().building=0 + ob:get_luaentity().fighting=1 + ob:get_luaentity().attack_chance=2 +--support for other mobs + ob:get_luaentity().attack_type="dogfight" + ob:get_luaentity().reach=2 + ob:get_luaentity().damage=3 + ob:get_luaentity().view_range=10 + ob:get_luaentity().walk_velocity= ob:get_luaentity().walk_velocity or 2 + ob:get_luaentity().run_velocity= ob:get_luaentity().run_velocity or 2 + elseif ob:is_player() then + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=5}},nil) + ob:set_properties({ + mesh = aliveai.character_model, + textures = {"aliveai_threats_mind_manipulator.png"} + }) + if ob:get_hp()<=0 and aliveai.registered_bots["bot"] and aliveai.registered_bots["bot"].bot=="aliveai:bot" then + local tex=ob:get_properties().textures + local pos=ob:get_pos() + local m=minetest.add_entity(pos, "aliveai:bot") + m:get_luaentity().attack_chance=2 + m:get_luaentity().type="monster" + m:get_luaentity().team="mind_manipulator" .. math.random(1,100) + m:get_luaentity().attack_players=1 + m:get_luaentity().attacking=1 + m:get_luaentity().talking=0 + m:get_luaentity().light=0 + m:get_luaentity().building=0 + m:get_luaentity().fighting=1 + m:setyaw(math.random(0,6.28)) + m:set_properties({ + mesh = aliveai.character_model, + textures = tex + }) + end + end + end + end +}) + + + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="cockroach", + team="bug", + texture={"aliveai_threats_cockroach.png","aliveai_threats_cockroach.png","aliveai_threats_cockroach.png","aliveai_threats_cockroach.png","aliveai_threats_cockroach.png","aliveai_threats_cockroach.png"}, + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + type="monster", + dmg=1, + hp=4, + name_color="", + arm=2, + coming=0, + smartfight=0, + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","group:stone"}, + attack_chance=2, + visual="cube", + visual_size={x=0.4,y=0.001}, + collisionbox={-0.1,0,-0.1,0.2,0.1,0.2}, + basey=0, + distance=10, + spawn_y=2, + on_load=function(self) + if self.clone then + self.object:remove() + end + end, + on_step=function(self,dtime) + if self.fight then + local pos=aliveai.roundpos(self.object:get_pos()) + local n=0 + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 20)) do + local en=ob:get_luaentity() + if en and en.name=="aliveai_threats:cockroach" then + n=n+1 + end + end + if n<10 then + for y=-2,5,1 do + for x=-2,2,1 do + for z=-2,2,1 do + local p1={x=pos.x+x,y=pos.y+y,z=pos.z+z} + local p2={x=pos.x+x,y=pos.y+y-1,z=pos.z+z} + local no1=minetest.get_node(p1).name + local no2=minetest.get_node(p2).name + if not (minetest.registered_nodes[no1] and minetest.registered_nodes[no2]) then return end + if minetest.registered_nodes[no1].walkable==false and minetest.registered_nodes[no2].walkable + and aliveai.visiable(pos,p1) then + local e=minetest.add_entity(p1,"aliveai_threats:cockroach") + e:get_luaentity().clone=1 + e:get_luaentity().fight=self.fight + e:get_luaentity().temper=3 + e:setyaw(math.random(0,6.28)) + n=n+1 + if n>=10 then + return + end + end + end + end + end + end + elseif self.clone and not self.fight then + aliveai.kill(self) + end + end, + click=function(self,clicker) + clicker:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=self.object:get_hp()*2}},nil) + end, + death=function(self,puncher,pos) + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 1, + texture = "default_dirt.png^[colorize:#000000cc", + collisiondetection = true, + }) + return self + end, +}) + + +aliveai.create_bot({ + attack_players=1, + name="ninja", + team="bug", + texture="aliveai_threats_ninja.png", + attacking=1, + talking=0, + light=0, + building=0, + start_with_items={["default:sword_steel"]=1}, + type="", + hp=30, + name_color="", + attack_chance=2, + on_step=function(self,dtime) + if not self.finvist and (self.fight or self.fly) then + self.finvist=true + self.object:set_properties({ + is_visible=false, + makes_footstep_sound=false, + textures={"aliveai_threats_i.png","aliveai_threats_i.png","aliveai_threats_i.png"} + }) + elseif self.finvist and not (self.fight or self.fight) then + self.finvist=nil + self.object:set_properties({ + is_visible=true, + makes_footstep_sound=true, + textures={"aliveai_threats_ninja.png","aliveai_threats_i.png","aliveai_threats_i.png"} + }) + elseif self.finvist and self.fight then + if math.random(1,10)<3 then + self.object:set_properties({is_visible=true}) + else + self.object:set_properties({is_visible=false}) + + if math.random(1,5)==1 then + local pos=self.object:get_pos() + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, self.distance/2)) do + local en=ob:get_luaentity() + if en and en.aliveai and en.fight and en.fight:get_luaentity() and en.fight:get_luaentity().aliveai and en.fight:get_luaentity().botname==self.botname then + ob:get_luaentity().fight=nil + end + end + end + + end + end + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + if self.finvist then + self.finvist=nil + self.object:set_properties({ + is_visible=true, + makes_footstep_sound=true, + textures={"aliveai_threats_ninja.png","aliveai_threats_i.png","aliveai_threats_i.png"}, + }) + end + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "default_dirt.png^[colorize:#000000cc", + collisiondetection = true, + }) + end +}) + +minetest.register_tool("aliveai_threats:quantumcore", { + description = "Quantum core", + inventory_image = "aliveai_threats_quantumcore.png", + range = 15, + on_use=function(itemstack, user, pointed_thing) + if user:get_luaentity() then user=user:get_luaentity() end + local type=pointed_thing.type + if type=="node" or type=="object" then + local pos=pointed_thing.above + if type=="object" then + pos=pointed_thing.ref:get_pos() + end + local n1=minetest.registered_nodes[minetest.get_node(pos).name] + pos.y=pos.y+1 + local n2=minetest.registered_nodes[minetest.get_node(pos).name] + if n1 and n2 and not (n1.walkable and n2.walkable) then + user:set_pos(pos) + end + else + local p=aliveai.random_pos(user:get_pos(),15) + if p then user:set_pos(p) end + end + + end, + on_place=function(itemstack, user, pointed_thing) + local p=aliveai.random_pos(user:get_pos(),15) + if p then user:set_pos(p) end + end +}) + +aliveai.create_bot({ + attack_players=1, + name="quantum_monster", + team="bug", + texture="aliveai_threats_quantum_monster.png", + attacking=1, + talking=0, + light=0, + building=0, + start_with_items={["aliveai_threats:quantumcore"]=1}, + type="", + hp=40, + name_color="", + visual_size={x=1,y=1.4}, + collisionbox={-0.33,-1.3,-0.33,0.33,1.2,0.33}, + spawn_y=1, + on_step=function(self,dtime) + if self.fight and not self.fly and (math.random(1,5)==1 or self.epunched) then + self.epunched=nil + local p=aliveai.roundpos(self.fight:get_pos()) + if not p then self.fight=nil return end + local pos={x=p.x+math.random(-1,4),y=p.y,z=p.z+math.random(-1,4)} + for i=-2,2,1 do + local pos1={x=pos.x,y=pos.y+i,z=pos.z} + local pos2={x=pos.x,y=pos.y+i+1,z=pos.z} + local pos3={x=pos.x,y=pos.y+i+2,z=pos.z} + local pos4={x=pos.x,y=pos.y+i+3,z=pos.z} + + local n1=minetest.registered_nodes[minetest.get_node(pos1).name] + local n2=minetest.registered_nodes[minetest.get_node(pos2).name] + local n3=minetest.registered_nodes[minetest.get_node(pos3).name] + local n4=minetest.registered_nodes[minetest.get_node(pos4).name] + + if n2 and n2.walkable==false and n1 and n3 and n4 and n1.walkable and not (n3.walkable and n4.walkable) then + pos2.y=pos2.y+1 + self.object:set_pos(pos2) + end + end + elseif self.fly and (self.epunched or aliveai.distance(self,self.fly:get_pos())0 and o.ob:getvelocity().y~=0 then + for ii, ob in pairs(minetest.get_objects_inside_radius(o.ob:get_pos(), 1.5)) do + local en=ob:get_luaentity() + if not en or (en.name~="__builtin:item" and not (en.aliveai and en.botname==o.n) ) then + ob:punch(o.ob,1,{full_punch_interval=1,damage_groups={fleshy=1}}) + o.ob:setvelocity({x=0, y=0, z=0}) + if o.on_hit_object then + o.on_hit_object(o.ob:get_luaentity(),o.ob:get_pos(),ob) + end + table.remove(aliveai_threats.debris,i) + break + end + end + else + + if o and o.on_hit_ground and o.ob:getvelocity() and o.ob:getvelocity().y==0 then + o.on_hit_ground(o.ob:get_luaentity(),o.ob:get_pos()) + end + table.remove(aliveai_threats.debris,i) + end + end +end) + + +aliveai.create_bot({ + attack_players=1, + name="natural_monster", + team="natural", + texture="aliveai_threats_natural_monster.png", + attacking=1, + talking=0, + light=0, + building=0, + type="monster", + hp=10, + name_color="", + collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}, + visual="cube", + basey=-0.5, + drop_dead_body=0, + escape=0, + spawn_on={"group:sand","group:soil","default:snow","default:snowblock","default:ice","group:leaves","group:tree","group:stone","group:cracky","group:level","group:crumbly","group:choppy"}, + attack_chance=2, + spawn_y=0, + spawn=function(self) + local pos=self.object:get_pos() + pos.y=pos.y-1.5 + if minetest.get_node(pos).name=="aliveai:spawner" then pos.y=pos.y-1 end + local drop=minetest.get_node_drops(minetest.get_node(pos).name)[1] + local n=minetest.registered_nodes[minetest.get_node(pos).name] + if not (n and n.walkable) or drop=="" or type(drop)~="string" then self.object:remove() return self end + local t=n.tiles + if not t[1] then self.object:remove() return self end + local tx={} + self.t1=t[1] + self.t2=t[1] + self.t3=t[1] + self.natural_monster=1 + self.consists=drop + self.team=self.consists + if t[2] then self.t2=t[2] self.t3=t[2] end + if t[3] and t[3].name then self.t3=t[3].name + elseif t[3] then self.t3=t[3] + end + if type(self.t3)=="table" then return end + tx[1]=self.t1 + tx[2]=self.t2 + tx[3]=self.t3 + tx[4]=self.t3 + tx[5]=self.t3 .."^aliveai_threats_natural_monster.png" + tx[6]=self.t3 + self.object:set_properties({textures=tx}) + self.cctime=0 + end, + on_load=function(self) + if self.natural_monster then + local tx={} + tx[1]=self.t1 + tx[2]=self.t2 + tx[3]=self.t3 + tx[4]=self.t3 + tx[5]=self.t3 .."^aliveai_threats_natural_monster.png" + tx[6]=self.t3 + self.object:set_properties({textures=tx}) + self.team=self.consists + self.cctime=0 + else + self.object:remove() + end + end, + on_step=function(self,dtime) + if self.fight and (self.cctime<1 or self.time==self.otime) then + self.cctime=5 + local d=aliveai.distance(self,self.fight:get_pos()) + if not (d>4 and d1 then + self.cctime=self.cctime-1 + end + end, + death=function(self,puncher,pos) + aliveai.invadd(self,self.consists,math.random(1, 4),false) + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + aliveai.lookat(self,pos) + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.2, + maxsize = 4, + texture = self.t1, + collisiondetection = true, + }) + end +}) + +aliveai.create_bot({ + type="npc", + name="stubborn_monster", + texture="aliveai_threats_stubborn_monster.png", + hp=20, + drop_dead_body=0, + usearmor=0, + on_load=function(self) + if not self.body or self.killed then self.spawn(self) return self end + local s={} + local c="" + local t="" + for i,v in ipairs(self.body) do + s["s"..v]=v + if i>1 then c="^" end + t=t .. c.. "aliveai_threats_stubborn_monster" .. v ..".png" + end + self.object:set_properties({ + mesh = aliveai.character_model, + textures = {t,"aliveai_threats_i.png","aliveai_threats_i.png"}, + }) + if not s["s3"] then self.nhead=true end + self.spawn(self) + end, + spawn=function(self) + if not self.body then + self.body={1,2,3} + end + self.hp2=self.object:get_hp() + self.deadtimer=10 + self.hurted=0 + if self.killed then + self.attack_players=1 + self.attacking=1 + self.team="stubborn" + self.talking=0 + self.light=0 + self.building=0 + self.type="monster" + self.escape=0 + self.attack_chance=1 + self.smartfight=0 + end + + end, + on_step=function(self,dtime) + if self.dead1 then + self.time=self.otime + self.deadtimer=self.deadtimer-1 + if self.deadtimer<0 then + self.object:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=self.hp*2}},nil) + end + return self + end + if self.lay then + self.time=self.otime + if math.random(0,5)==1 then + aliveai.anim(self,"stand") + self.lay=nil + end + return self + end + if self.nhead then + self.fight=nil + self.fly=nil + self.temper=0 + self.come=nil + end + end, + on_punched=function(self,puncher,h) + self.hurted=h + end, + death=function(self,puncher,pos) + local r=math.random(1,5) + if r>3 then + if self.basey==-0.5 then local pos=self.object:get_pos() self.object:set_pos({x=pos.x,y=pos.y+1,z=pos.z}) end + aliveai.anim(self,"lay") + self.lay=true + end + if r<3 or not self.killed then + r=math.random(1,3) + table.remove(self.body,r) + local t="" + local c="" + local c2=0 + for i,v in ipairs(self.body) do + if i>1 then c="^" end + t=t .. c.. "aliveai_threats_stubborn_monster" .. v ..".png" + c2=i + end + self.object:set_properties({ + mesh = aliveai.character_model, + textures = {t,"aliveai_threats_i.png","aliveai_threats_i.png"}, + }) + if r==1 or c2==1 or self.hurted>self.hp_max then + if self.basey==-0.5 then self.object:set_properties({mesh = aliveai.character_model}) local pos=self.object:get_pos() self.object:set_pos({x=pos.x,y=pos.y+1,z=pos.z}) end + aliveai.anim(self,"lay") + self.object:set_hp(self.hp_max) + self.hp=self.hp_max + self.dead1=true + return self + end + if r==3 then self.nhead=true end + if not self.killed then + self.killed=1 + self.spawn(self) + end + end + if not self.dead1 then + self.hp_max=self.hp_max-2 + self.object:set_hp(self.hp_max) + self.hp=self.hp_max + end + end +}) + + +aliveai.create_bot({ + drop_dead_body=0, + attack_players=1, + name="slime", + team="slime", + texture="aliveai_threats_slime.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["aliveai_threats:slime"]=2}, + type="monster", + dmg=2, + hp=10, + name_color="", + on_step=function(self,dtime) + if self.setslime and aliveai.gethp(self.fight)<=0 then + minetest.add_entity(self.setslime, "aliveai_threats:slime") + self.setslime=nil + end + end, + on_punching=function(self,target) + self.setslime=target:get_pos() + end, + death=function(self,puncher,pos) + minetest.add_particlespawner({ + amount = 15, + time =0.1, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=2, y=2, z=2}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 3, + texture = "default_dirt.png^[colorize:#00aa00aa", + collisiondetection = true, + }) + end, +}) + +minetest.register_node("aliveai_threats:slime", { + description = "Slime", + tiles = {"default_river_water.png^[colorize:#00aa00aa"}, + alpha = 200, + walkable = false, + pointable = true, + drowning = 1, + buildable_to = true, + drawtype = "glasslike", + post_effect_color = {a = 248, r =0, g = 255, b = 0}, + damage_per_second = 1, + paramtype = "light", + liquid_viscosity = 15, + liquidtype = "source", + liquid_range = 0, + liquid_alternative_flowing = "aliveai_threats:slime", + liquid_alternative_source = "aliveai_threats:slime", + groups = {liquid = 4,crumbly = 1,not_in_creative_inventory=1} +}) + +aliveai.create_bot({ + name="killerplant", + type="", + texture="default_grass_5.png^[colorize:#00ff0022", + talking=0, + light=0, + building=0, + type="monster", + name_color="", + collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}, + visual="cube", + basey=-0.5, + drop_dead_body=0, + spawn_on={"group:sand","group:soil","group:stone","group:cracky","group:level","group:crumbly","group:choppy"}, + spawn_y=0, + spawn=function(self) + local pos=self.object:get_pos() + local opos=pos + local npos + local n + for i=0,10,1 do + npos={x=pos.x,y=pos.y-i,z=pos.z,} + n=minetest.registered_nodes[minetest.get_node(npos).name] + if n and n.walkable then + minetest.set_node(opos,{name="aliveai_threats:killerplant"}) + aliveai.kill(self) + return + end + opos=npos + end + aliveai.kill(self) + end, +}) + + +minetest.register_node("aliveai_threats:killerplant", { + description = "Killerplant", + groups = {attached_node=1,choppy = 1,not_in_creative_inventory=1}, + tiles = {"default_grass_5.png^[colorize:#00ff0022"}, + paramtype="light", + walkable=false, + sounds = default.node_sound_leaves_defaults(), + drawtype = "plantlike", + selection_box = { + type = "fixed", + fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5} + }, + on_construct = function(pos) + local meta=minetest.get_meta(pos) + meta:set_string("owner","plant") + minetest.get_node_timer(pos):start(3) + end, + on_timer = function (pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius({x=pos.x,y=pos.y-2.5,z=pos.z}, 2)) do + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=1}}) + end + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 1.5)) do + minetest.sound_play("default_grass_footstep", {pos=pos,max_hear_distance = 10, gain = 0.5}) + ob:moveto({x=pos.x,y=pos.y-3,z=pos.z}) + end + return true + end, +}) + + +aliveai.create_bot({ + attack_players=1, + name="bee", + team="bug", + floating=1, + texture={"aliveai_threats_bee.png","aliveai_threats_bee.png","aliveai_threats_bee.png","aliveai_threats_bee.png","aliveai_threats_bee.png","aliveai_threats_bee.png"}, + attacking=1, + talking=0, + light=0, + building=0, + type="monster", + hp=2, + name_color="", + collisionbox={-0.2,-0.2,-0.2,0.2,0.2,0.2}, + visual_size={x=0.1,y=0.1}, + visual="cube", + basey=-0.5, + drop_dead_body=0, + escape=0, + spawn_on={"group:sand","group:soil","default:snow","default:snowblock","default:ice","group:leaves","group:tree","group:stone","group:cracky","group:level","group:crumbly","group:choppy"}, + attack_chance=2, + spawn_y=0, + death=function(self,puncher,pos) + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.2, + maxsize = 1, + texture ="aliveai_threats_bee.png", + collisiondetection = true, + }) + end +}) + + + + +minetest.register_tool("aliveai_threats:quake_core", { + description = "Quake core", + inventory_image = "default_dirt.png", + on_use=function(itemstack, user, pointed_thing) + if user:get_luaentity() then user=user:get_luaentity() end + local type=pointed_thing.type + local pos1=user:get_pos() + pos1.y=pos1.y+1.5 + local pos2 + if type=="object" then + pos2=pointed_thing.ref:get_pos() + elseif type=="node" then + pos2=pointed_thing.under + elseif type=="nothing" then + local dir + if user:get_luaentity() then + if user:get_luaentity().aliveai and user:get_luaentity().fight then + local dir=aliveai.get_dir(user:get_luaentity(),user:get_luaentity().fight) + pos2={x=pos1.x+(dir.x*15),y=pos1.y+(dir.y*15),z=pos1.z+(dir.z*15)} + else + pos2=aliveai.pointat(user:get_luaentity(),15) + end + else + local dir=user:get_look_dir() + pos2={x=pos1.x+(dir.x*15),y=pos1.y+(dir.y*15),z=pos1.z+(dir.z*15)} + end + else + return itemstack + end + + local n=minetest.get_node(pos1).name + if minetest.registered_nodes[n] and minetest.registered_nodes[n].walkable then return end + aliveai_threats.quake(pos1,pos2) + itemstack:add_wear(65535/50) + return itemstack + end, +}) + + +aliveai_threats.quake=function(pos1,pos2) + if aliveai_threats.n>20 then return end + aliveai_threats.n=aliveai_threats.n+1 + local d=math.floor(aliveai.distance(pos1,pos2)+0.5) + local dir={x=(pos1.x-pos2.x)/-d,y=(pos1.y-pos2.y)/-d,z=(pos1.z-pos2.z)/-d} + local p1 + local p2 + local i1=1 + local ii=15 + for i=1,d,1 do + ii=i + p1={x=pos1.x+(dir.x*i),y=pos1.y,z=pos1.z+(dir.z*i)} + p2={x=p1.x+math.random(-1,1),y=pos1.y,z=p1.z+math.random(-1,1)} + if not p1.x or p1.x~=p1.x or not p2.x or p2.x~=p2.x then + return + end + aliveai_threats.quaking(p2,i,i1) + aliveai_threats.quaking(p1,i,i1) + i1=i1+1 + if i1>3 then i1=1 end + end + minetest.after((ii*0.1)+10, function() + aliveai_threats.n=aliveai_threats.n-1 + end) + +end + +aliveai_threats.close=function(re,i1,lo) + for i, p in pairs(re) do + if aliveai.def(p.p,"buildable_to") then + minetest.set_node(p.p,{name=p.n}) + end + end + + if lo>7 and re[#re] and (i1==1 or lo<25) then + for _, ob in ipairs(minetest.get_objects_inside_radius(re[#re].p, 3)) do + ob:punch(ob,20,{full_punch_interval=1,damage_groups={fleshy=9000}}) + end + end +end + +aliveai_threats.quaking=function(pos,i2,i1) + local pos2 + local s + local re={} + for i=0,-30,-1 do + pos2={x=pos.x,y=pos.y+i,z=pos.z} + if aliveai.def(pos2,"is_ground_content") and + minetest.get_item_group(minetest.get_node(pos2).name, "cracky")~=0 or + minetest.get_item_group(minetest.get_node(pos2).name, "soil")~=0 and + minetest.is_protected(pos2,"")==false then + + table.insert(re,{n=minetest.get_node(pos2).name,p=pos2}) + + if s then + s=s+1 + minetest.set_node(pos2,{name="air"}) + else + s=0 + minetest.after(i2*0.1, function(pos2) + minetest.set_node(pos2,{name="air"}) + end, pos2) + end + elseif s then + minetest.after((i2*0.1)+10, function(re) + aliveai_threats.close(re,i1,s) + end, re) + return + end + end + if s then + minetest.after((i2*0.1)+10, function(re) + aliveai_threats.close(re,i1,s) + end, re) + end +end + +aliveai.create_bot({ + attack_players=1, + name="quake", + team="quak", + texture="default_dirt.png", + stealing=1, + steal_chanse=2, + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["default:dirt"]=5,["default:stone"]=5,["aliveai_threats:quake_core"]=1}, + type="monster", + dmg=1, + hp=40, + name_color="", + spawn_on={"group:sand","group:soail","default:stone"}, + tool_near=1, + tool_chance=2 +}) + + + +aliveai.create_bot({ + attack_players=1, + name="pull_master_monster", + team="pull", + texture="aliveai_threats_pull.png^[colorize:#00000044", + attacking=1, + talking=0, + light=-1, + lowest_light=9, + building=0, + smartfight=0, + escape=0, + type="monster", + dmg=5, + hp=200, + arm=5, + name_color="", + spawn_on={"group:sand","group:spreading_dirt_type","group:stone","default:snow"}, + attack_chance=3, + spawn_y=1, + visual_size={x=2,y=1.5}, + collisionbox={-0.7,-1.5,-0.7,0.7,1.2,0.7}, + start_with_items={["default:mese_crystal"]=1,["aliveai:relive"]=2}, + on_punching=function(self,target) + local pos=aliveai.roundpos(target:get_pos()) + local n + for i=-2,-6,-1 do + n=minetest.registered_nodes[minetest.get_node({x=pos.x,y=pos.y+i,z=pos.z}).name] + if n and n.walkable==false then + return + end + end + pos.y=pos.y-4 + target:set_pos(pos) + if minetest.is_protected(pos,"")==false then + minetest.set_node(pos,{name="aliveai_threats:slime"}) + end + end, + on_step=function(self,dtime) + if self.fight and math.random(1,20)==1 then + local c=0 + for _, ob in ipairs(aliveai.active) do + local en=ob:get_luaentity() + if en and en.name=="aliveai_threats:pull_monster" then + if en.lifetimer and en.lifetimer20 then return end + end + end + end + + for i=0,math.random(2,10),1 do + local p=aliveai.random_pos(self,5,10) + if p then + local n + local p1=1 + for i=-2,-5,-1 do + n=minetest.registered_nodes[minetest.get_node({x=p.x,y=p.y+i,z=p.z}).name] + if n and n.walkable==false then + p1=nil + end + end + if p1 then + p.y=p.y-3 + local en=minetest.add_entity(p, "aliveai_threats:pull_monster"):get_luaentity() + en.temper=2 + en.fight=self.fight + end + end + end + end + end, + on_punched=function(self,puncher) + self.object:set_properties({ + mesh = aliveai.character_model, + textures = {"aliveai_threats_pull.png"}, + }) + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = self.tex or "default_dirt.png", + collisiondetection = true, + }) + self.tex=nil + if self.sleep or self.hide then self.abortsleep=true end + if self.hide or not self.fight then return end + if not self.ohp then self.ohp=self.object:get_hp()*0.8 return end + if self.ohp>self.object:get_hp() then + local pos=self.object:get_pos() + local n=minetest.get_node(pos) + if minetest.registered_nodes[n.name] and minetest.registered_nodes[n.name].walkable then return end + self.hide=true + self.ohp=nil + self.time=0.2 + self.pull_down=nil + return self + end + end, + death=function(self,puncher,pos) + if not self.ex then + self.ex=1 + aliveai_nitroglycerine.explode(pos) + minetest.after(1, function(self) + if self and self.ex then self.ex=nil end + end,self) + end + return self + end, +}) + + +aliveai.create_bot({ + attack_players=1, + name="stick_man", + team="bug", + texture="aliveai_threats_ninja.png", + attacking=1, + talking=0, + light=0, + building=0, + hp=15, + name_color="", + visual_size={x=0.2,y=1}, + type="monster", + on_punched=function(self,puncher) + local pos=self.object:get_pos() + if self.finvist then + self.finvist=nil + self.object:set_properties({ + is_visible=true, + makes_footstep_sound=true, + textures={"aliveai_threats_ninja.png","aliveai_threats_i.png","aliveai_threats_i.png"}, + }) + end + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "default_dirt.png^[colorize:#000000cc", + collisiondetection = true, + }) + end +}) + +aliveai.create_bot({ + attack_players=1, + name="bronze_terminator", + team="nuke", + texture="aliveai_threats_terminator_bronze.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + start_with_items={["default:bronze_ingot"]=4,["default:bronzeblock"]=1}, + type="monster", + dmg=5, + hp=200, + arm=2, + name_color="", + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","group:stone"}, + attack_chance=5, + floating=1, + on_punching=function(self,target) + if not self.att and self.object:getvelocity().y==0 then + self.att=target + self.att:set_attach(self.object, "", {x=0,y=0,z=0}, {x=0,y=2,z=0}) + self.att_pos=self.object:get_pos() + self.controlled=1 + self.att_a=self.att:getacceleration() + end + end, + on_step=function(self,dtime) + if self.att then + self.object:setvelocity({x=math.random(-3,3), y=10, z=math.random(-3,3)}) + aliveai.punch(self,self.att) + if self.object:get_pos().y-self.att_pos.y>40 then + self.att:set_detach() + minetest.after(0.5, function(self) + if self.att then + self.att:setacceleration(self.att_a) + self.att=nil + end + self.object:set_pos(self.att_pos) + self.controlled=nil + end,self) + end + + end + end, + on_load=function(self) + self.hp2=self.object:get_hp() + end, + spawn=function(self) + self.hp2=self.object:get_hp() + end, + on_punched=function(self,puncher) + if self.hp2 and self.hp2-self.object:get_hp()<5 then + self.object:set_hp(self.hp2) + return self + end + local pos=self.object:get_pos() + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "default_bronze_block.png", + collisiondetection = true, + spawn_chance=100, + }) + end, + death=function(self,puncher,pos) + aliveai.floating(self) + if self.att then + self.att:set_detach() + end + end + + +}) + +if aliveai.spawning then +minetest.register_abm({ + nodenames = {"group:tree"}, + interval = 30, + chance = 300, + action = function(pos) + aliveai_threats_eyes.spawn(pos) + end, +}) +end + + +aliveai.create_bot({ + attack_players=1, + name="jumper", + team="natural", + texture="default_dirt.png^aliveai_threats_eyes.png", + talking=0, + light=0, + building=0, + type="monster", + hp=10, + dmg=2, + name_color="", + collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}, + visual="cube", + basey=-0.5, + drop_dead_body=0, + escape=0, + spawn_on={"group:sand","group:soil","default:snow","default:snowblock","default:ice","group:leaves","group:tree","group:stone","group:cracky","group:level","group:crumbly","group:choppy"}, + attack_chance=2, + spawn_y=0, + smartfight=0, + spawn=function(self) + local pos=self.object:get_pos() + pos.y=pos.y-1.5 + if minetest.get_node(pos).name=="aliveai:spawner" then pos.y=pos.y-1 end + local drop=minetest.get_node_drops(minetest.get_node(pos).name)[1] + local n=minetest.registered_nodes[minetest.get_node(pos).name] + if not (n and n.walkable) or drop=="" or type(drop)~="string" then self.object:remove() return self end + local t=n.tiles + if not t[1] then self.object:remove() return self end + local tx={} + self.t1=t[1] + self.t2=t[1] + self.t3=t[1] + self.natural_monster=1 + self.consists=drop + self.team=self.consists + if t[2] then self.t2=t[2] self.t3=t[2] end + if t[3] and t[3].name then self.t3=t[3].name + elseif t[3] then self.t3=t[3] + end + if type(self.t3)=="table" then return end + + tx[1]=self.t1 + tx[2]=self.t2 + tx[3]=self.t3 + tx[4]=self.t3 + tx[5]=self.t3 .."^aliveai_threats_eyes.png" + tx[6]=self.t3 + + self.object:set_properties({textures=tx}) + self.textxs=tx + self.jtimer=0 + end, + on_load=function(self) + if self.natural_monster then + local tx={} + tx[1]=self.t1 + tx[2]=self.t2 + tx[3]=self.t3 + tx[4]=self.t3 + tx[5]=self.t3 .."^aliveai_threats_eyes.png" + tx[6]=self.t3 + self.object:set_properties({textures=tx}) + self.team=self.consists + self.textxs=tx + else + self.object:remove() + end + self.jtimer=0 + end, + on_step=function(self,dtime) + local v=self.object:getvelocity() + if self.jtimer>1 and v.y==0 then + aliveai.jump(self) + self.jtimer=0 + else + self.jtimer=self.jtimer+1 + end + if self.fight and not self.fight_before then + local t=self.textxs + t[5]=self.t3 .."^aliveai_threats_eyes_mad.png" + self.object:set_properties({textures=t}) + self.fight_before=1 + elseif not self.fight and self.fight_before then + local t=self.textxs + t[5]=self.t3 .."^aliveai_threats_eyes.png" + self.object:set_properties({textures=t}) + self.fight_before=nil + end + end, + death=function(self,puncher,pos) + aliveai.invadd(self,self.consists,math.random(1, 4),false) + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + aliveai.lookat(self,pos) + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-2, y=-2, z=-2}, + maxvel = {x=1, y=0.5, z=1}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.2, + maxsize = 4, + texture = self.t1, + collisiondetection = true, + }) + end +}) + +aliveai_threats.acid=function(ob) + if aliveai.gethp(ob,1)<1 then return end + + if ob:is_player() and aliveai_threats.stopacidplayer[ob:get_player_name()] then + return + end + + local pos=ob:get_pos() + minetest.add_particlespawner({ + amount = 3, + time =0.1, + minpos = pos, + maxpos = pos, + minvel = {x=-1, y=-1, z=-1}, + maxvel = {x=1, y=-1, z=1}, + minacc = {x=0, y=-9, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.1, + maxsize = 2, + texture = "default_dirt.png^[colorize:#00aa00ff", + collisiondetection = true, + }) + aliveai.punchdmg(ob) + if aliveai.gethp(ob,1)<1 then + if ob:is_player() then + aliveai_threats.stopacidplayer[ob:get_player_name()]=1 + minetest.after(10, function(ob) + aliveai_threats.stopacidplayer[ob:get_player_name()]=nil + end,ob) + end + return + end + + minetest.after(math.random(1,4), function() + aliveai_threats.acid(ob) + end) +end + + +minetest.register_tool("aliveai_threats:acid", { + description = "Acid", + inventory_image = "aliveai_relive.png^[colorize:#00aa00aa", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type~="object" or aliveai.team(pointed_thing.ref)=="nuke" then return end + aliveai_threats.acid(pointed_thing.ref) + itemstack:add_wear(6000) + return itemstack + end +}) + + +aliveai.create_bot({ + attack_players=1, + name="acidman", + team="nuke", + texture="aliveai_threats_acidman.png", + attacking=1, + talking=0, + light=0, + building=0, + escape=0, + type="monster", + hp=50, + name_color="", + arm=2, + coming=0, + smartfight=0, + spawn_on={"group:sand","group:spreading_dirt_type","default:gravel","group:stone"}, + attack_chance=5, + start_with_items={["aliveai_threats:acid"]=1}, + tool_near=1, + tool_chance=1, + on_blow=function(self) + aliveai.kill(self) + self.death(self,self.object,self.object:getpos()) + end, + death=function(self,puncher,pos) + if not self.ex then + self.ex=true + aliveai_nitroglycerine.explode(pos,{ + radius=1, + set="air", + blow_nodes=0, + hurt=0 + }) + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 4)) do + if aliveai.visiable(pos,ob:get_pos()) then aliveai_threats.tox(ob) end + end + end + return self + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + aliveai_threats.acid(puncher) + minetest.add_particlespawner({ + amount = 5, + time=0.2, + minpos = pos, + maxpos = pos, + minvel = {x=-0.1, y=-0.1, z=-0.1}, + maxvel = {x=0.1, y=0.1, z=0.1}, + minacc = {x=0, y=0, z=0}, + maxacc = {x=0, y=0, z=0}, + minexptime = 0.5, + maxexptime = 1, + minsize = 0.5, + maxsize = 2, + texture = "default_grass.png^[colorize:#00ff00aa", + }) + end +}) + + +aliveai.create_bot({ + attack_players=1, + name="fangs", + team="fangs", + texture="default_dirt.png^aliveai_threats_fangs.png", + talking=0, + light=0, + building=0, + type="monster", + hp=100, + arm=2, + name_color="", + collisionbox={-1,-1,-1,1,1,1}, + visual="cube", + drop_dead_body=0, + escape=0, + spawn_on={"group:sand","group:soil","default:snow"}, + attack_chance=1, + spawn_y=2, + smartfight=0, + spawn=function(self,t,t2) + local tx="" + if not t then + tx="aliveai_threats:fangs" + elseif t==1 then + tx="aliveai_threats:fangs_fight" + elseif t2 and t2:is_player() then + t2:set_eye_offset({x=0, y=0, z=0}, {x=0, y=0, z=0}) + else + tx="aliveai_threats:fangs_attack" + end + self.fangs=t + self.object:set_properties({visual="wielditem",visual_size={x=1.2,y=1.2},textures={tx}}) + end, + on_load=function(self) + self.spawn(self) + end, + on_step=function(self,dtime) + if self.eating then + if not self.eating:get_attach() then + self.spawn(self,3,self.eating) + self.eating=nil + return + end + local hp=aliveai.gethp(self.eating) + if self.eating:get_luaentity() then + if self.eating:get_luaentity().health then + self.eating:get_luaentity().health=hp-2 + elseif self.eating:get_luaentity().hp then + self.eating:get_luaentity().hp=hp-2 + end + elseif self.eating:is_player() then + self.eating:set_hp(hp-2) + end + if self.fangs then + self.spawn(self) + end + aliveai.punchdmg(self.eating,2) + if hp<=0 then + self.eating:set_detach() + if self.eating:get_luaentity() then + self.eating:remove() + else + local pos=aliveai.roundpos(self.eating:get_pos()) + local n + for i=-2,-6,-1 do + if not aliveai.def({x=pos.x,y=pos.y+i,z=pos.z},"walkable") then + return + end + end + pos.y=pos.y-4 + self.eating:set_pos(pos) + end + self.spawn(self,3,self.eating) + self.eating=nil + self.object:set_hp(100) + aliveai.showhp(self,true) + return + end + end + if not self.eating and self.fight then + if self.fight:get_attach() then + self.fight=nil + return + end + if aliveai.distance(self,self.fight:get_pos())<2.5 then + self.eating=self.fight + self.eating:set_attach(self.object, "",{x=0, y=-3 , z=0}, {x=0, y=0, z=0}) + if self.eating:is_player() then + self.eating:set_eye_offset({x=0, y=-15, z=0}, {x=0, y=0, z=0}) + end + self.spawn(self,2) + return self + else + self.spawn(self,1) + end + elseif self.fangs and not self.fight then + self.spawn(self) + elseif not self.fight and math.random(1,3)==1 then + for _, ob in ipairs(minetest.get_objects_inside_radius(self.object:getpos(), self.distance)) do + local pos=ob:get_pos() + if aliveai.is_bot(ob) and aliveai.team(ob)~=self.team and aliveai.viewfield(self,pos) then + local en=ob:get_luaentity() + if en.dying or en.dead then + self.fight=ob + self.temper=self.temper+1 + return self + end + end + end + end + end, + death=function(self,puncher,pos) + if self.eating and self.eating:get_attach() then + self.eating:set_detach() + self.spawn(self,3,self.eating) + end + aliveai.invadd(self,"default:dirt",math.random(1, 4),false) + minetest.add_particlespawner({ + amount = 30, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-5, y=0, z=-5}, + maxvel = {x=5, y=5, z=5}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 2, + maxsize = 8, + texture = "default_dirt.png", + collisiondetection = true, + }) + + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + aliveai.lookat(self,pos) + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-5, y=0, z=-5}, + maxvel = {x=5, y=5, z=5}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.2, + maxsize = 8, + texture = "default_dirt.png", + collisiondetection = true, + }) + end +}) +local fangsbox = { + type = "fixed", + fixed = { + {0.2, -0.5, -0.5, 0.5, 0.5, 0.5}, + {-0.5, 0.2, -0.5, 0.5, 0.5, 0.5}, + {-0.5, -0.5, 0.2, 0.5, 0.5, 0.5}, + {-0.5, -0.5, -0.5, -0.2, 0.5, 0.5}, + {-0.5, -0.5, -0.5, 0.5, -0.2, 0.5}, + {-0.5, -0.5, -0.5, 0.5, 0.5, -0.2}, + } +} +minetest.register_node("aliveai_threats:fangs", { + tiles = {"default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png"}, + groups = {cracky = 2,not_in_creative_inventory=1}, + drawtype="nodebox", + node_box = fangsbox +}) +minetest.register_node("aliveai_threats:fangs_fight", { + tiles = {"default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png^aliveai_threats_fangs.png","default_dirt.png"}, + groups = {cracky = 2,not_in_creative_inventory=1}, + drawtype="nodebox", + node_box = fangsbox +}) +minetest.register_node("aliveai_threats:fangs_attack", { + tiles = {"default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png","default_dirt.png^aliveai_threats_fangs2.png","default_dirt.png"}, + groups = {cracky = 2,not_in_creative_inventory=1}, + drawtype="nodebox", + node_box = fangsbox +}) + + +minetest.register_abm{ + nodenames = {"air"}, + neighbors = {"group:soil","group:stone"}, + interval = 300, + chance = 10000, + action = function(pos) + if not minetest.is_protected(pos,"") and minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}).name=="air" then + minetest.set_node(pos, {name = "aliveai_threats:statue"}) + end + end, +} + +minetest.register_node("aliveai_threats:statue", { + description = "Statue", + tiles = {"aliveai_air.png"}, + inventory_image = "default_stone.png", + wield_image = "default_stone.png", + groups = {cracky = 1,level=3,stone=1}, + sounds = default.node_sound_stone_defaults(), + paramtype = "light", + sunlight_propagates = true, + drawtype="glasslike", + visual_scale = 0.12, + post_effect_color = {a=255, r=0, g=0, b=0}, + selection_box ={ + type = "fixed", + fixed = { + {-0.4, -0.5, -0.4, 0.4, 1.2, 0.4}, + } + }, + on_construct = function(pos) + minetest.add_entity({x=pos.x,y=pos.y-0.5,z=pos.z}, "aliveai_threats:statue") + minetest.get_node_timer(pos):start(5) + end, + on_destruct = function(pos) + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 1)) do + local en=ob:get_luaentity() + if en and en.name=="aliveai_threats:statue" then + ob:remove() + end + end + end, + on_timer = function (pos, elapsed) + local l=minetest.get_node_light(pos) + if l and l>5 then return true end + local o + local cfo + local c=0 + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 1)) do + local en=ob:get_luaentity() + if en and en.name=="aliveai_threats:statue" then + cfo=ob + break + end + + end + if not cfo then + minetest.add_entity({x=pos.x,y=pos.y-0.5,z=pos.z}, "aliveai_threats:statue") + return true + end + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 15)) do + local en=ob:get_luaentity() + if not (en and (en.type==nil or en.name=="aliveai_threats:statue")) and aliveai.visiable(pos,ob:get_pos()) then + c=c+1 + if c>1 then return true end + o=ob + + end + end + if not o then + return true + end + local d + local opos=o:get_pos() + if o:get_luaentity() then + d=aliveai.pointat(o:get_luaentity(),1) + elseif o:is_player(o) then + d=o:get_look_dir() + d={x=d.x*1.1,y=d.y*1.1,z=d.z*1.1} + d={x=opos.x+d.x,y=opos.y+d.y,z=opos.z+d.z} + else + return true + end + local self=cfo:get_luaentity() + local p=aliveai.pointat(self,1) + if aliveai.distance(pos,d)>aliveai.distance(pos,opos) then + if minetest.get_node(p).name=="aliveai_threats:statue" then + return true + end + if not aliveai.def(p,"buildable_to") + and aliveai.def({x=p.x,y=p.y+1,z=p.z},"buildable_to") then + if not aliveai.def({x=p.x,y=p.y+2,z=p.z},"buildable_to") then + return true + end + p={x=p.x,y=p.y+1,z=p.z} + elseif aliveai.def(p,"buildable_to") + and aliveai.def({x=p.x,y=p.y-1,z=p.z},"buildable_to") then + if aliveai.def({x=p.x,y=p.y-2,z=p.z},"buildable_to") then + return true + end + p={x=p.x,y=p.y-1,z=p.z} + end + if not aliveai.def(p,"buildable_to") or minetest.is_protected(p,"") then + return true + end + minetest.set_node(p,{name="aliveai_threats:statue"}) + minetest.remove_node(pos) + if aliveai.distance(p,opos)<1 then + aliveai.punchdmg(o,50) + end + for _, ob in ipairs(minetest.get_objects_inside_radius(p, 1)) do + local en=ob:get_luaentity() + if en and en.name=="aliveai_threats:statue" then + aliveai.lookat(en,opos) + return true + end + end + end + return true + end, +}) +minetest.register_entity("aliveai_threats:statue",{ + hp_max = 10, + physical =false, + pointable=false, + visual = "mesh", + mesh=aliveai.character_model, + textures ={"default_stone.png"}, + on_activate=function(self, staticdata) + if not minetest.get_node(self.object:get_pos()).name=="aliveai_threats:statue" then + self.object:remove() + end + end, +}) +aliveai.loaded("aliveai_threats:statue") + +minetest.register_node("aliveai_threats:hat", { + tiles = {"default_coal_block.png^[colorize:#000000aa"}, + groups = {dig_immediate = 3,not_in_creative_inventory=1}, + on_construct = function(pos) + minetest.get_node_timer(pos):start(math.random(1,10)) + end, + on_timer = function (pos, elapsed) + if minetest.get_node({x=pos.x, y=pos.y-1 , z=pos.z}).name=="default:snowblock" then + minetest.add_entity({x=pos.x, y=pos.y-1 , z=pos.z}, "aliveai_threats:snowman") + minetest.remove_node({x=pos.x, y=pos.y-1 , z=pos.z}) + minetest.remove_node(pos) + end + return false + end, + drawtype="nodebox", + node_box ={ + type = "fixed", + fixed = { + {-0.375, -0.5, -0.375, 0.375, -0.4375, 0.375}, + {-0.22, -0.4375, -0.22, 0.22, 0.0625, 0.22} + } + } +}) + +minetest.register_entity("aliveai_threats:hat",{ + hp_max = 20, + physical =true, + pointable=false, + visual = "wielditem", + textures ={"aliveai_threats:hat"}, + visual_size={x=2,y=2}, + on_step=function(self, dtime) + self.t=self.t+dtime + if self.t<1 then return end + self.t=0 + if not self.object:get_attach() then + self.object:remove() + end + end, + t=0, +}) + + + +minetest.register_node("aliveai_threats:snowman", { + tiles = {"default_snow.png"}, + groups = {cracky = 2,not_in_creative_inventory=1}, + drawtype="nodebox", + node_box ={ + type = "fixed", + fixed = { + {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, + {-0.375, 0.5, -0.375, 0.375, 1.2, 0.375}, + {-0.25, 1.2, -0.25, 0.25, 1.6, 0.25} + } + } +}) + + +aliveai.create_bot({ + attack_players=1, + name="snowman", + team="snow", + texture="default_snow.png", + talking=0, + light=0, + building=0, + type="monster", + hp=10, + arm=2, + name_color="", + collisionbox={-0.5,-0.45,-0.5,0.5,2.0,0.5}, + visual="cube", + drop_dead_body=0, + escape=0, + start_with_items={["default:snow"]=1,["default:snowblock"]=3,["aliveai_threats:hat"]=1}, + spawn_on={"default:snow","default:snowblock"}, + attack_chance=1, + basey=-1, + smartfight=0, + spawn_chance=100, + spawn=function(self,t,t2) + self.object:set_properties({visual="wielditem",visual_size={x=0.6,y=0.6},textures={"aliveai_threats:snowman"}}) + local e=minetest.add_entity(self.object:getpos(), "aliveai_threats:hat") + e:set_attach(self.object, "",{x=0, y=62 , z=0}, {x=0, y=0, z=0}) + self.hat=e + self.cctime=0 + end, + on_load=function(self) + self.spawn(self) + end, + on_step=function(self,dtime) + if self.fight and (self.cctime<1 or self.time==self.otime) then + self.cctime=5 + local d=aliveai.distance(self,self.fight:get_pos()) + if not (aliveai.viewfield(self,self.fight) and aliveai.visiable(self,self.fight:get_pos())) then return end + local pos=self.object:get_pos() + local ta=self.fight:get_pos() + if not (ta and pos) then return end + ta.y=ta.y+1.5 + aliveai.stand(self) + aliveai.lookat(self,ta) + local e=minetest.add_item(aliveai.pointat(self,2),"default:snow") + local dir=aliveai.get_dir(self,ta) + e:setvelocity({x = dir.x*30, y = dir.y*30, z = dir.z*30}) + e:get_luaentity().age=(tonumber(minetest.setting_get("item_entity_ttl")) or 900)-2 + table.insert(aliveai_threats.debris,{ob=e,n=self.botname}) + return self + elseif self.fight and self.cctime>1 then + self.cctime=self.cctime-1 + end + + end, + death=function(self,puncher,pos) + if self.hat and self.hat:get_attach() then + self.hat:set_detach() + self.hat:remove() + end + minetest.add_particlespawner({ + amount = 30, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-5, y=0, z=-5}, + maxvel = {x=5, y=5, z=5}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 2, + maxsize = 4, + texture = "default_snow.png", + collisiondetection = true, + }) + minetest.sound_play("default_snow_footstep", {pos=pos, gain = 1.0, max_hear_distance = 5,}) + end, + on_punched=function(self,puncher) + local pos=self.object:get_pos() + if self.hp<6 and self.hp>0 and not minetest.is_protected(pos,"") and aliveai.def(pos,"buildable_to") and math.random(1,5)==1 then + minetest.set_node(pos,{name="default:snowblock"}) + local psa={x=pos.x,y=pos.y+1,z=pos.z} + if not minetest.is_protected(psa,"") and aliveai.def(psa,"buildable_to") then + self.inv["aliveai_threats:hat"]=nil + minetest.set_node(psa,{name="aliveai_threats:hat"}) + end + aliveai.punchdmg(self.object,100) + end + aliveai.lookat(self,pos) + minetest.add_particlespawner({ + amount = 5, + time =0.05, + minpos = pos, + maxpos = pos, + minvel = {x=-5, y=0, z=-5}, + maxvel = {x=5, y=5, z=5}, + minacc = {x=0, y=-8, z=0}, + maxacc = {x=0, y=-10, z=0}, + minexptime = 2, + maxexptime = 1, + minsize = 0.2, + maxsize = 2, + texture = "default_snow.png", + collisiondetection = true, + }) + end +}) \ No newline at end of file diff --git a/aliveai_threats/lab.lua b/aliveai_threats/lab.lua new file mode 100644 index 0000000..20f472f --- /dev/null +++ b/aliveai_threats/lab.lua @@ -0,0 +1,712 @@ +aliveai_threats.lab={ + furnishings1={"vessels:shelf","aliveai:chair","aliveai_threats:timed_bumb","aliveai_threats:timed_nitrobumb","aliveai_threat_eletric:timed_ebumb","aliveai_threats:landmine","aliveai_threats:deadlock","aliveai_massdestruction:nuclearbarrel"}, + furnishings2={"vessels:steel_bottle","vessels:glass_bottle","vessels:drinking_glass","aliveai_threats:toxic_tank","aliveai_threats:labbottle_containing","aliveai_threats:labbottle"}, + cam={"aliveai_threats:secam","aliveai_threats:secam2","aliveai_threat_eletric:secam"} + } + +minetest.register_tool("aliveai_threats:labspawner", { + description = "labspawner", + range=15, + groups={not_in_creative_inventory=1}, + inventory_image = "default_stick.png", + on_use = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" then + aliveai_threats.lab.spawning(pointed_thing.under,1) + end + end, + on_place = function(itemstack, user, pointed_thing) + if pointed_thing.type=="node" then + aliveai_threats.lab.gen_stair2(pointed_thing.above) + end + end +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "aliveai_threats:lab_spawner", + wherein = "default:stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 1, + clust_size = 1, + y_min = -100, + y_max = 20, +}) + +minetest.register_ore({ + ore_type = "scatter", + ore = "aliveai_threats:lab_spawner", + wherein = "default:desert_stone", + clust_scarcity = 36 * 36 * 36, + clust_num_ores = 1, + clust_size = 1, + y_min = -100, + y_max = 20, +}) + +minetest.register_abm({ + nodenames = {"aliveai_threats:lab_spawner"}, + interval = 1, + chance = 10, + action = function(pos, node, active_object_count, active_object_count_wider) + minetest.set_node(pos,{name="default:stone"}) + aliveai_threats.lab.spawning(pos) + end +}) + +aliveai_threats.lab.spawning=function(p,nrnd) + if not nrnd and math.random(1,100)~=1 then return end + local pos4 + for i=1,20,1 do + pos4={x=p.x,y=p.y+i,z=p.z} + local get_light=minetest.get_node_light(pos4) + if minetest.get_node(pos4).name=="ignore" or (get_light and get_light>3) or minetest.is_protected(pos4,"") then return end + end + p={x=p.x-20,y=p.y-3,z=p.z-20} + local sta + local by=math.random(4,6) + local bx=12 + local bz=12 + local floor=math.random(1,4) + local cfloor=0 + local croom=0 + aliveai_threats.lab.gen_stairs2=1 + for y=6,floor*6,6 do + cfloor=cfloor+1 + for x=0,24,12 do + for z=0,24,12 do + croom=croom+1 + aliveai_threats.lab.gen_room({x=p.x+x,y=p.y+y,z=p.z+z},bx,by,bz,floor,cfloor,croom) + end + end + end + + if aliveai_threats.lab.gen_stairs2==1 then --force add stair if none is spawned + aliveai_threats.lab.gen_stair2({x=p.x+12+1,y=p.y+(floor*6)+1,z=p.z+12+1}) + aliveai_threats.lab.gen_stairs2=nil + end + +end + + + +aliveai_threats.lab.spawn=function(pos) + local bots={} + local c=0 + for i, v in pairs(aliveai.registered_bots) do + if (v.team=="nuke" or v.team=="alien") and v.mod_name~="aliveai_massdestruction" then + table.insert(bots,v.bot) + end + end + local addbot=bots[aliveai.random(1,#bots)] + if addbot then minetest.add_entity(pos, addbot) end +end + +aliveai_threats.lab.gen_stair2=function(pos) + + local ys=0 + local base="default:silver_sandstone_brick" + local stair="stairs:stair_steelblock" + + local pos3 + local get_light + local light="aliveai_threats:lablight" + local light2="aliveai_threats:lablight2" + local set_timer=false + for i=1,1000,1 do + pos3={x=pos.x,y=pos.y+i,z=pos.z} + get_light=minetest.get_node_light(pos3) + if minetest.get_node(pos3).name=="ignore" then return end + if i>6 and get_light and get_light>3 and pos3.y>7 and aliveai.def(pos3,"buildable_to") then + ys=i-1 + break + end + end + if ys==0 then return end + pos3={x=pos.x+2,y=pos3.y-1,z=pos.z+2} + local pos4 + for y=0,6,1 do + for x=-6,6,1 do + for z=-6,6,1 do + pos4={x=pos3.x+x,y=pos3.y+y,z=pos3.z+z} + if not minetest.is_protected(pos4,"") then + if (y==0 or y==6 or x==-6 or x==6 or z==-6 or z==6) and not ((y==1 or y==2) and (x==0 or z==0)) then + minetest.set_node(pos4,{name=base}) + elseif y==5 and ((x==-4 and z==-4) or (x==4 and z==4) or (x==-4 and z==4) or (x==4 and z==-4)) then + local r=math.random(1,4) + if r==3 then + local r2=math.random(1,#aliveai_threats.lab.cam) + if aliveai_threats.lab.cam[r2] then + minetest.set_node(pos4,{name=aliveai_threats.lab.cam[r2],param2=21}) + minetest.get_meta(pos4):set_string("team","nuke") + minetest.get_node_timer(pos4):start(1) + end + elseif r==1 then + minetest.set_node(pos4,{name=light}) + elseif r==2 then + minetest.set_node(pos4,{name=light2}) + minetest.get_node_timer(pos4):start(1) + else + minetest.set_node(pos4,{name=light2}) + end + else + minetest.set_node(pos4,{name="air"}) + end + end + end + end + end + + local a={x=0,y=0,z=0} + + local pos2 + local n + local k=true + local m + local p=0 + + local st=(ys+1)*5*5 + local s=0 + local ss=0 + local set_timer=false + for y=0,ys,1 do + for x=-1,5,1 do + for z=-1,5,1 do + ss=ss+1 + pos2={x=pos.x+x,y=pos.y+y,z=pos.z+z} + if y==a.y and x==a.x and z==a.z then --stair + n=stair + a.y=a.y+1 + s=s+1 + if s<=4 then + p=1 + if s==1 then p=2 end + a.x=a.x+1 + elseif s<=8 then + if s==5 then p=1 end + a.z=a.z+1 + elseif s<=12 then + p=3 + if s==9 then p=0 end + a.x=a.x-1 + elseif s<=16 then + p=2 + if s==13 then p=3 end + a.z=a.z-1 + if s==16 then s=0 end + end + elseif y==ys and not (x==-1 or x==5 or z==-1 or z==5) then --floor table + n="aliveai_threats:labtable2" + set_timer=true + elseif s==5 and x==4 and z==4 then + local r=math.random(1,4) + if r==1 then + n=light + elseif r==2 then + n=light2 + set_timer=true + else + n=light2 + end + p=12 + elseif y>=4 and (x==-1 or x==5 or z==-1 or z==5) then --walls + n=base + elseif y<4 and (x==-1 or x==5 or z==-1 or z==5) then + n="" + elseif y2 and ((z==0 and x>0) or (z==1 and x==4)) then --hole + n="air" + if y==5 and (x==1 or x==2) then + n="aliveai_threats:labtable2" + end + else --clean + n="air" + if y>2 then n="" end + end + + if n~="" then --set + pos2={x=pos.x+x,y=pos.y+y,z=pos.z+z} + minetest.set_node(pos2,{name=n,param2=p}) + end + p=0 + + end + end + end +end + +aliveai_threats.lab.gen_room=function(pos,bx,by,bz,floor,cfloor,croom) + if not pos then return end + pos=aliveai.roundpos(pos) + + local base="default:silver_sandstone_brick" + local n="air" + local door="aliveai:door_steel" + local light="aliveai_threats:lablight" + local light2="aliveai_threats:lablight2" + local furn="aliveai_threats:labtable" + local pos2 + local set_timer=false + local get_light=0 + local m=nil + local d={} + local a={x=bx,y=by,z=bz} + + local doors={ + x1=math.random(1,5)>1, + x2=math.random(1,5)>1, + z1=math.random(1,5)>1, + z2=math.random(1,5)>1, + xb1=math.random(1,5)>1, + xb2=math.random(1,5)>1, + zb1=math.random(1,5)>1, + zb2=math.random(1,5)>1 + } + + + local wall={n=0, + x1=math.random(0,20)>5, + x2=math.random(0,20)>5, + z1=math.random(0,20)>5, + z2=math.random(0,20)>5 + } +--door inside ... pos of 1/2 box + local x1=a.x/2 + local z1=a.z/2 +--door boxes sides + local x2a=a.x/4 + local x2b=a.x-x2a + local z2a=a.z/4 + local z2b=a.z-z2a +--walls count + + if wall.x1 then wall.n=wall.n+1 end + if wall.x2 then wall.n=wall.n+1 end + if wall.z1 then wall.n=wall.n+1 end + if wall.z2 then wall.n=wall.n+1 end + + + local all_nodes={} + + for y=0,a.y,1 do + for x=0,a.x,1 do + for z=0,a.z,1 do + pos2={x=pos.x+x,y=pos.y+y,z=pos.z+z} + + get_light=minetest.get_node_light(pos2) + + if (get_light and get_light>7) or minetest.is_protected(pos2,"") then return end + + if x==0 or x==a.x --wall box + or y==0 + or y==a.y + or z==0 or z==a.z then + if (y==1 or y==2) and ((x==x2a and doors.xb1) or (x==x2b and doors.xb2) or (z==z2a and doors.zb1) or (z==z2b and doors.zb2)) and minetest.get_node(pos2).name==base then + if y==1 then + n=door + else + n="air" + end + else + n=base + end + elseif y==1 and ((x==1 and z==1) or (x==x1+1 and z==z1+1)) then --set stair + if aliveai_threats.lab.gen_stairs2 and cfloor==floor and (math.random(1,20)==1 or croom==9) then + aliveai_threats.lab.gen_stairs2=nil + n="stair2" + elseif cfloor1 and ( --middle walls + (wall.x1 and xx1 and z==z1) or + (wall.z1 and zx1 and x==x1)) then + if (y==1 or y==2) and ( --door + (doors.x1 and wall.x1 and x==x1/2) or + (doors.x2 and wall.x2 and x==x1*1.5) or + (doors.z1 and wall.z1 and z==z1/2) or + (doors.z2 and wall.z2 and z==z1*1.5)) then + if y==1 then + n=door + else + n="air" + end + else + n=base + end + elseif wall.n>1 and x==x1 and z==z1 then --center + n=base + elseif y==a.y-1 and ((x==x2a and z==z2a) or (x==x2b and z==z2b) or (x==x2a and z==z2b) or (x==x2b and z==z2a)) then + local r=math.random(1,10) + if r==5 and math.random(1,2)==1 then + local r2=math.random(1,#aliveai_threats.lab.cam) + if aliveai_threats.lab.cam[r2] then + n=aliveai_threats.lab.cam[r2] + m=1 + set_timer=true + end + elseif r>4 then + n=light + elseif r<4 then + n=light2 + else + n=light + set_timer=true + end + elseif y==1 and (x==1 or z==1 or x==a.x-1 or z==a.z-1) then --set furns + n=furn + set_timer=true + else --else + n="air" + end + + table.insert(all_nodes,{n=n,pos=pos2,m=m}) + m=nil + if set_timer then + set_timer=false + minetest.get_node_timer(pos2):start(1) + end + end + end + end + for i, v in pairs(all_nodes) do + if v.m then + minetest.set_node(v.pos,{name=v.n,param2=21}) + minetest.get_meta(pos):set_string("team","nuke") + elseif v.n=="stair" then + minetest.after(math.random(1), function(v) + aliveai_threats.lab.gen_stair(v.pos) + end,v) + elseif v.n=="stair2" then + minetest.after(math.random(1), function(v) + aliveai_threats.lab.gen_stair2(v.pos) + end,v) + else + minetest.set_node(v.pos,{name=v.n}) + end + end + +end + + +minetest.register_node("aliveai_threats:lablight", { + description = "Lab light", + tiles = {"default_cloud.png"}, + drawtype = "nodebox", + groups = {snappy = 3, not_in_creative_inventory=0}, + sounds = default.node_sound_glass_defaults(), + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + node_box = {type="fixed",fixed={-0.2,0.3,-0.4,0.2,0.5,0.4}}, + light_source=14, + on_punch = function(pos, node, puncher, pointed_thing) + if minetest.is_protected(pos,puncher:get_player_name())==false then + minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 5}) + minetest.get_node_timer(pos):start(1) + minetest.swap_node(pos, {name = "aliveai_threats:lablight2",param2=minetest.get_node(pos).param2}) + end + end, + on_timer = function (pos, elapsed) + if math.random(3)==1 then + minetest.swap_node(pos, {name = "aliveai_threats:lablight2",param2=minetest.get_node(pos).param2}) + end + return true + end, + on_blast=function(pos) + minetest.get_node_timer(pos):start(1) + end, +}) + +minetest.register_node("aliveai_threats:lablight2", { + description = "Lab light damaged (off)", + tiles = {"default_cloud.png"}, + drawtype = "nodebox", + groups = {snappy = 3, not_in_creative_inventory=1}, + sounds = default.node_sound_glass_defaults(), + is_ground_content = false, + node_box = {type="fixed",fixed={-0.2,0.3,-0.4,0.2,0.5,0.4}}, + drop="aliveai_threats:lablight", + paramtype2 = "facedir", + on_construct = function(pos) + minetest.get_node_timer(pos):start(1) + end, + on_timer = function (pos, elapsed) + if math.random(3)==1 then + minetest.swap_node(pos, {name = "aliveai_threats:lablight",param2=minetest.get_node(pos).param2}) + end + return true + end, + on_blast=function(pos) + minetest.get_node_timer(pos):stop() + end, + on_punch = function(pos, node, puncher, pointed_thing) + if minetest.is_protected(pos,puncher:get_player_name())==false then + minetest.sound_play("default_break_glass", {pos=pos, gain = 1.0, max_hear_distance = 5}) + minetest.get_node_timer(pos):stop() + end + end, +}) + +minetest.register_node("aliveai_threats:labtable2", { + description = "Lab table2", + tiles = {"default_silver_sandstone_brick.png"}, + drawtype = "nodebox", + node_box = {type="fixed",fixed={-0.5,0.4,-0.5,0.5,0.5,0.5}}, + groups = {cracky = 3, not_in_creative_inventory=1}, + sounds = default.node_sound_stone_defaults(), + is_ground_content = false, + on_timer = function (pos, elapsed) + for i=1,3,1 do + if aliveai.def({x=pos.x,y=pos.y-i,z=pos.z},"walkable") then + minetest.set_node(pos,{name="air"}) + return false + end + end + return false + end, +}) + +minetest.register_node("aliveai_threats:lab_spawner", { + description = "Lab spawner", + drawtype="airlike", + groups = {not_in_creative_inventory=1}, + is_ground_content = false +}) + +minetest.register_node("aliveai_threats:deadlock", { + description = "Deadlock", + groups = {cracky=3,not_in_creative_inventory=1}, + tiles={"default_steel_block.png^aliveai_threats_quantum_monster_lights.png"}, + paramtype = "light", + is_ground_content = false, + 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_node_timer(pos):start(1) + end, + on_timer = function (pos, elapsed) + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 1)) do + if aliveai.is_bot(ob) then + ob:get_luaentity().timer=-1 + return true + end + end + return true + end, +}) + +minetest.register_node("aliveai_threats:toxic_tank", { + description = "Toxic tank", + groups = {cracky=3,snappy = 3,not_in_creative_inventory=1}, + tiles={"default_glass.png"}, + special_tiles = { + { + name = "default_lava_source_animated.png^[colorize:#d8ff2d77", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 1, + }, + }, + }, + paramtype = "light", + is_ground_content = false, + drawtype = "glasslike_framed", + paramtype2 = "glasslikeliquidlevel", + sounds = default.node_sound_glass_defaults(), + on_punch = function(pos, node, puncher, pointed_thing) + minetest.get_node_timer(pos):start(1) + end, + + on_construct = function(pos) + local a=math.random(32,64) + minetest.get_meta(pos):set_int("v",a) + minetest.swap_node(pos, {name = "aliveai_threats:toxic_tank",param2=a}) + end, + on_timer = function (pos, elapsed) + local v=minetest.get_meta(pos):get_int("v") + minetest.get_meta(pos):set_int("v",v-1) + + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 3)) do + if aliveai.visiable(pos,ob:get_pos()) then aliveai_threats.tox(ob) end + end + if v>0 then + minetest.swap_node(pos, {name = "aliveai_threats:toxic_tank",param2=v}) + return true + else + minetest.set_node(pos,{name="default:glass"}) + return false + end + end, +}) + +minetest.register_node("aliveai_threats:labbottle_containing", { + description = "Lab bottle", + groups = {not_in_creative_inventory=1,dig_immediate = 3, attached_node = 1}, + inventory_image = "aliveai_threats_testbottle_containin.png", + tiles={"aliveai_threats_testbottle_containin.png"}, + paramtype = "light", + is_ground_content = false, + drawtype = "plantlike", + walkable = false, + sounds = default.node_sound_glass_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.27, -0.5, -0.27, 0.27, 0.2, 0.27} + }, + drop = { + max_items=2, + items = { + {items = {"aliveai_threats:labbottle"}}, + {items = {"aliveai:hypnotics"}, rarity = 2}, + {items = {"aliveai_threats:mind_manipulator"}, rarity = 3}, + {items = {"aliveai_threats:acid"}, 2}, + {items = {"aliveai_massdestruction:blackholecore"}, rarity = 2}, + {items = {"aliveai:relive"}, rarity = 2}, + {items = {"aliveai:team_gift"}, rarity = 3}, + }} +}) +minetest.register_node("aliveai_threats:labbottle", { + description = "Lab bottle", + groups = {vessel = 1, not_in_creative_inventory=1,dig_immediate = 3, attached_node = 1}, + tiles={"aliveai_threats_testbottle.png"}, + inventory_image = "aliveai_threats_testbottle.png", + paramtype = "light", + is_ground_content = false, + drawtype = "plantlike", + walkable = false, + sounds = default.node_sound_glass_defaults(), + selection_box = { + type = "fixed", + fixed = {-0.27, -0.5, -0.27, 0.27, 0.2, 0.27} + }, + on_use = function(itemstack, user, pointed_thing) + local pos=user:get_pos() + local dir=user:get_look_dir() + local e=minetest.add_item({x=pos.x+(dir.x*2),y=pos.y+2+(dir.y*2),z=pos.z+(dir.z*2)},"aliveai_threats:labbottle") + local vc = {x = dir.x*15, y = dir.y*15, z = dir.z*15} + e:setvelocity(vc) + e:get_luaentity().age=(tonumber(minetest.setting_get("item_entity_ttl")) or 900)-10 + e:get_luaentity().on_punch=nil + e:get_luaentity().hp_max=10 + table.insert(aliveai_threats.debris,{ob=e,n=user:get_player_name()}) + itemstack:take_item() + return itemstack + end, +}) + +minetest.register_craft( { + output = "vessels:glass_fragments", + recipe = { + {"aliveai_threats:labbottle"}, + {"aliveai_threats:labbottle"}, + } +}) + +minetest.override_item("vessels:drinking_glass", { + on_use = function(itemstack, user, pointed_thing) + local pos=user:get_pos() + local dir=user:get_look_dir() + local e=minetest.add_item({x=pos.x+(dir.x*2),y=pos.y+2+(dir.y*2),z=pos.z+(dir.z*2)},"vessels:drinking_glass") + local vc = {x = dir.x*15, y = dir.y*15, z = dir.z*15} + e:setvelocity(vc) + e:get_luaentity().age=(tonumber(minetest.setting_get("item_entity_ttl")) or 900)-10 + table.insert(aliveai_threats.debris,{ob=e,n=user:get_player_name()}) + itemstack:take_item() + return itemstack + end, +}) +minetest.override_item("vessels:glass_bottle", { + on_use = function(itemstack, user, pointed_thing) + local pos=user:get_pos() + local dir=user:get_look_dir() + local e=minetest.add_item({x=pos.x+(dir.x*2),y=pos.y+2+(dir.y*2),z=pos.z+(dir.z*2)},"vessels:glass_bottle") + local vc = {x = dir.x*15, y = dir.y*15, z = dir.z*15} + e:setvelocity(vc) + e:get_luaentity().age=(tonumber(minetest.setting_get("item_entity_ttl")) or 900)-10 + table.insert(aliveai_threats.debris,{ob=e,n=user:get_player_name()}) + itemstack:take_item() + return itemstack + end, +}) + +minetest.register_node("aliveai_threats:labtable", { + description = "Lab table", + tiles = {"default_silver_sandstone_block.png^[colorize:#ffffff77"}, + groups = {cracky = 3, not_in_creative_inventory=1}, + sounds = default.node_sound_stone_defaults(), + is_ground_content = false, + on_timer = function (pos, elapsed) + local d="aliveai:door_steel" + if minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z}).name==d + or minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z}).name==d + or minetest.get_node({x=pos.x,y=pos.y,z=pos.z+1}).name==d + or minetest.get_node({x=pos.x,y=pos.y,z=pos.z-1}).name==d then + minetest.set_node(pos,{name="air"}) + return false + end + local r1=math.random(1,5) + if r1>3 then + local n=math.random(1,#aliveai_threats.lab.furnishings2+5) + if aliveai_threats.lab.furnishings2[n] then + pos.y=pos.y+1 + minetest.set_node(pos,{name=aliveai_threats.lab.furnishings2[n]}) + end + elseif r1==3 and math.random(1,10)==1 then + local n=math.random(1,#aliveai_threats.lab.furnishings1) + if aliveai_threats.lab.furnishings1[n] then + minetest.set_node(pos,{name=aliveai_threats.lab.furnishings1[n]}) + if aliveai_threats.lab.furnishings1[n]=="aliveai_threats:deadlock" then + aliveai_threats.lab.spawn(pos) + end + end + elseif r1<3 then + minetest.set_node(pos,{name="air"}) + if math.random(1,30)==1 then + aliveai_threats.lab.spawn(pos) + end + end + return false + end, +}) diff --git a/aliveai_threats/models/aliveai_threats_crystal.obj b/aliveai_threats/models/aliveai_threats_crystal.obj new file mode 100644 index 0000000..50e387c --- /dev/null +++ b/aliveai_threats/models/aliveai_threats_crystal.obj @@ -0,0 +1,94 @@ +# Blender v2.78 (sub 0) OBJ File: 'pollution_crystal.blend' +# www.blender.org +mtllib pollution_crystal.mtl +o Cube_Cube.001 +v -0.031811 0.002414 0.031811 +v -0.031811 0.066037 0.031811 +v -0.031811 0.002414 -0.031811 +v -0.031811 0.066037 -0.031811 +v 0.031811 0.002414 0.031811 +v 0.031811 0.066037 0.031811 +v 0.031811 0.002414 -0.031811 +v 0.031811 0.066037 -0.031811 +v -0.003181 0.116534 0.003181 +v -0.003181 0.116534 -0.003181 +v 0.003181 0.116534 0.003181 +v 0.003181 0.116534 -0.003181 +v -0.012462 -0.264709 0.012462 +v -0.012462 -0.264709 -0.012462 +v 0.012462 -0.264709 0.012462 +v 0.012462 -0.264709 -0.012462 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn 0.9974 -0.0722 0.0000 +vn 0.0000 0.4932 -0.8699 +vn 0.0000 1.0000 0.0000 +vn 0.8699 0.4932 0.0000 +vn -0.8699 0.4932 0.0000 +vn 0.0000 0.4932 0.8699 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 -0.0722 0.9974 +vn 0.0000 -0.0722 -0.9974 +vn -0.9974 -0.0722 0.0000 +usemtl Material.002 +s off +f 1/1/1 2/2/1 4/3/1 3/4/1 +f 3/5/2 4/6/2 8/7/2 7/8/2 +f 7/9/3 8/10/3 6/11/3 5/12/3 +f 5/13/4 6/14/4 2/15/4 1/16/4 +f 7/9/5 5/17/5 15/18/5 16/19/5 +f 8/20/6 4/6/6 10/21/6 12/22/6 +f 12/23/7 10/24/7 9/25/7 11/26/7 +f 6/27/8 8/10/8 12/28/8 11/26/8 +f 4/29/9 2/2/9 9/25/9 10/30/9 +f 2/31/10 6/14/10 11/32/10 9/33/10 +f 14/34/11 16/35/11 15/18/11 13/36/11 +f 5/13/12 1/37/12 13/38/12 15/39/12 +f 3/5/13 7/40/13 16/41/13 14/42/13 +f 1/1/14 3/43/14 14/44/14 13/36/14 diff --git a/aliveai_threats/models/aliveai_threats_crystals.obj b/aliveai_threats/models/aliveai_threats_crystals.obj new file mode 100644 index 0000000..78eced3 --- /dev/null +++ b/aliveai_threats/models/aliveai_threats_crystals.obj @@ -0,0 +1,549 @@ +# Blender v2.78 (sub 0) OBJ File: 'pollution_crystals.blend' +# www.blender.org +mtllib pollution_crystals.mtl +o Cube_Cube.001 +v 0.023448 1.441446 0.586645 +v 0.023448 2.541710 0.586645 +v 0.023448 1.441446 -0.513619 +v 0.023448 2.541710 -0.513619 +v 1.123712 1.441446 0.586645 +v 1.123712 2.541710 0.586645 +v 1.123712 1.441446 -0.513619 +v 1.123712 2.541710 -0.513619 +v 0.518567 3.414985 0.091526 +v 0.518567 3.414985 -0.018500 +v 0.628593 3.414985 0.091526 +v 0.628593 3.414985 -0.018500 +v 0.358072 -3.178070 0.252021 +v 0.358072 -3.178070 -0.178995 +v 0.789088 -3.178070 0.252021 +v 0.789088 -3.178070 -0.178995 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn 0.9974 -0.0722 0.0000 +vn 0.0000 0.4932 -0.8699 +vn 0.0000 1.0000 0.0000 +vn 0.8699 0.4932 0.0000 +vn -0.8699 0.4932 0.0000 +vn 0.0000 0.4932 0.8699 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 -0.0722 0.9974 +vn 0.0000 -0.0722 -0.9974 +vn -0.9974 -0.0722 0.0000 +usemtl Material.002 +s off +f 1/1/1 2/2/1 4/3/1 3/4/1 +f 3/5/2 4/6/2 8/7/2 7/8/2 +f 7/9/3 8/10/3 6/11/3 5/12/3 +f 5/13/4 6/14/4 2/15/4 1/16/4 +f 7/9/5 5/17/5 15/18/5 16/19/5 +f 8/20/6 4/6/6 10/21/6 12/22/6 +f 12/23/7 10/24/7 9/25/7 11/26/7 +f 6/27/8 8/10/8 12/28/8 11/26/8 +f 4/29/9 2/2/9 9/25/9 10/30/9 +f 2/31/10 6/14/10 11/32/10 9/33/10 +f 14/34/11 16/35/11 15/18/11 13/36/11 +f 5/13/12 1/37/12 13/38/12 15/39/12 +f 3/5/13 7/40/13 16/41/13 14/42/13 +f 1/1/14 3/43/14 14/44/14 13/36/14 +o Cube.001_Cube.000 +v -1.894439 2.054051 0.079474 +v -2.195457 3.333790 -0.070682 +v -1.947618 1.863163 -1.440799 +v -2.248636 3.142902 -1.590955 +v -0.288794 2.419751 -0.022609 +v -0.589812 3.699489 -0.172765 +v -0.341973 2.228863 -1.542881 +v -0.642991 3.508601 -1.693038 +v -1.735764 4.428179 -0.919921 +v -1.741082 4.409090 -1.071949 +v -1.575200 4.464748 -0.930129 +v -1.580517 4.445660 -1.082157 +v -0.158446 -3.265836 0.216506 +v -0.179278 -3.340614 -0.379043 +v 0.470547 -3.122577 0.176517 +v 0.449715 -3.197355 -0.419033 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -0.9732 -0.2216 0.0619 +vn -0.0347 -0.1245 -0.9916 +vn 0.9732 0.2216 -0.0619 +vn 0.0347 0.1245 0.9916 +vn 0.9897 0.1337 -0.0514 +vn -0.1539 0.4269 -0.8911 +vn -0.2275 0.9671 -0.1135 +vn 0.6633 0.7393 -0.1160 +vn -0.9260 0.3773 -0.0150 +vn -0.0959 0.6351 0.7665 +vn 0.2275 -0.9671 0.1135 +vn 0.0536 0.0432 0.9976 +vn -0.0155 -0.2050 -0.9786 +vn -0.9488 -0.3077 0.0718 +usemtl Material.000 +s off +f 17/45/15 18/46/15 20/47/15 19/48/15 +f 19/49/16 20/50/16 24/51/16 23/52/16 +f 23/53/17 24/54/17 22/55/17 21/56/17 +f 21/57/18 22/58/18 18/59/18 17/60/18 +f 23/53/19 21/61/19 31/62/19 32/63/19 +f 24/64/20 20/50/20 26/65/20 28/66/20 +f 28/67/21 26/68/21 25/69/21 27/70/21 +f 22/71/22 24/54/22 28/72/22 27/70/22 +f 20/73/23 18/46/23 25/69/23 26/74/23 +f 18/75/24 22/58/24 27/76/24 25/77/24 +f 30/78/25 32/79/25 31/62/25 29/80/25 +f 21/57/26 17/81/26 29/82/26 31/83/26 +f 19/49/27 23/84/27 32/85/27 30/86/27 +f 17/45/28 19/87/28 30/88/28 29/80/28 +o Cube.002 +v 1.019832 0.351057 -0.502994 +v 1.367006 0.919804 -0.732864 +v 0.504731 0.273778 -1.472158 +v 0.851905 0.842524 -1.702028 +v 1.827034 -0.294273 -0.880556 +v 2.174208 0.274473 -1.110426 +v 1.311933 -0.371553 -1.849720 +v 1.659107 0.197194 -2.079590 +v 1.774001 1.046041 -1.521338 +v 1.722491 1.038313 -1.618254 +v 1.854721 0.981508 -1.559094 +v 1.803211 0.973780 -1.656010 +v -0.348957 -2.256623 0.052547 +v -0.550742 -2.286896 -0.327111 +v -0.032745 -2.509424 -0.095358 +v -0.234530 -2.539697 -0.475017 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -0.7336 0.5865 0.3432 +vn -0.4682 -0.0702 -0.8808 +vn 0.7336 -0.5865 -0.3432 +vn 0.4682 0.0702 0.8808 +vn 0.6737 -0.6735 -0.3043 +vn -0.0242 0.4822 -0.8758 +vn 0.4925 0.8069 -0.3261 +vn 0.8758 0.0955 -0.4731 +vn -0.2230 0.9740 0.0408 +vn 0.6770 0.5873 0.4435 +vn -0.4925 -0.8069 0.3261 +vn 0.4099 -0.0209 0.9119 +vn -0.5205 -0.1604 -0.8386 +vn -0.7843 0.4922 0.3776 +usemtl Material.001 +s off +f 33/89/29 34/90/29 36/91/29 35/92/29 +f 35/93/30 36/94/30 40/95/30 39/96/30 +f 39/97/31 40/98/31 38/99/31 37/100/31 +f 37/101/32 38/102/32 34/103/32 33/104/32 +f 39/97/33 37/105/33 47/106/33 48/107/33 +f 40/108/34 36/94/34 42/109/34 44/110/34 +f 44/111/35 42/112/35 41/113/35 43/114/35 +f 38/115/36 40/98/36 44/116/36 43/114/36 +f 36/117/37 34/90/37 41/113/37 42/118/37 +f 34/119/38 38/102/38 43/120/38 41/121/38 +f 46/122/39 48/123/39 47/106/39 45/124/39 +f 37/101/40 33/125/40 45/126/40 47/127/40 +f 35/93/41 39/128/41 48/129/41 46/130/41 +f 33/89/42 35/131/42 46/132/42 45/124/42 +o Cube.003 +v 2.253079 3.729011 -0.132745 +v 2.700144 5.055216 -0.203345 +v 2.198353 3.710644 -0.824298 +v 2.645419 5.036849 -0.894898 +v 3.065754 3.452025 -0.189699 +v 3.512820 4.778230 -0.260299 +v 3.011029 3.433659 -0.881253 +v 3.458094 4.759863 -0.951853 +v 3.396056 5.974911 -0.596208 +v 3.390583 5.973074 -0.665363 +v 3.477323 5.947213 -0.601903 +v 3.471851 5.945376 -0.671059 +v 0.606566 -1.928959 -0.063972 +v 0.585128 -1.936154 -0.334880 +v 0.924922 -2.037465 -0.086283 +v 0.903484 -2.044660 -0.357192 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -0.9445 0.3219 0.0662 +vn -0.0789 -0.0265 -0.9965 +vn 0.9445 -0.3219 -0.0662 +vn 0.0789 0.0265 0.9965 +vn 0.9293 -0.3636 -0.0639 +vn 0.0103 0.2304 -0.9731 +vn 0.3190 0.9464 -0.0504 +vn 0.9968 0.0072 -0.0791 +vn -0.7871 0.6152 0.0459 +vn 0.1622 0.2813 0.9458 +vn -0.3190 -0.9464 0.0504 +vn 0.0674 -0.0075 0.9977 +vn -0.0902 -0.0604 -0.9941 +vn -0.9577 0.2795 0.0684 +usemtl Material.003 +s off +f 49/133/43 50/134/43 52/135/43 51/136/43 +f 51/137/44 52/138/44 56/139/44 55/140/44 +f 55/141/45 56/142/45 54/143/45 53/144/45 +f 53/145/46 54/146/46 50/147/46 49/148/46 +f 55/141/47 53/149/47 63/150/47 64/151/47 +f 56/152/48 52/138/48 58/153/48 60/154/48 +f 60/155/49 58/156/49 57/157/49 59/158/49 +f 54/159/50 56/142/50 60/160/50 59/158/50 +f 52/161/51 50/134/51 57/157/51 58/162/51 +f 50/163/52 54/146/52 59/164/52 57/165/52 +f 62/166/53 64/167/53 63/150/53 61/168/53 +f 53/145/54 49/169/54 61/170/54 63/171/54 +f 51/137/55 55/172/55 64/173/55 62/174/55 +f 49/133/56 51/175/56 62/176/56 61/168/56 +o Cube.004 +v -1.694765 2.986474 3.834678 +v -1.899361 4.593619 4.538314 +v -1.968595 3.940166 1.576767 +v -2.173192 5.547312 2.280403 +v 0.611890 3.337655 3.703268 +v 0.407293 4.944800 4.406904 +v 0.338060 4.291347 1.445356 +v 0.133463 5.898493 2.148992 +v -1.146978 6.456398 4.021592 +v -1.174361 6.551767 3.795801 +v -0.916312 6.491516 4.008451 +v -0.943695 6.586885 3.782660 +v -0.217511 -3.364362 0.153758 +v -0.324781 -2.990764 -0.730752 +v 0.686095 -3.226791 0.102280 +v 0.578825 -2.853193 -0.782231 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -0.9870 -0.1503 0.0562 +vn -0.1110 0.3867 -0.9155 +vn 0.9870 0.1503 -0.0562 +vn 0.1110 -0.3867 0.9155 +vn 0.9936 0.0628 -0.0940 +vn -0.1589 0.8679 -0.4705 +vn -0.1158 0.9099 0.3984 +vn 0.7201 0.6662 0.1941 +vn -0.8591 0.4258 0.2840 +vn 0.0152 0.2616 0.9651 +vn 0.1158 -0.9099 -0.3984 +vn 0.1221 -0.4763 0.8708 +vn -0.0988 0.2932 -0.9509 +vn -0.9715 -0.2364 0.0180 +usemtl Material.004 +s off +f 65/177/57 66/178/57 68/179/57 67/180/57 +f 67/181/58 68/182/58 72/183/58 71/184/58 +f 71/185/59 72/186/59 70/187/59 69/188/59 +f 69/189/60 70/190/60 66/191/60 65/192/60 +f 71/185/61 69/193/61 79/194/61 80/195/61 +f 72/196/62 68/182/62 74/197/62 76/198/62 +f 76/199/63 74/200/63 73/201/63 75/202/63 +f 70/203/64 72/186/64 76/204/64 75/202/64 +f 68/205/65 66/178/65 73/201/65 74/206/65 +f 66/207/66 70/190/66 75/208/66 73/209/66 +f 78/210/67 80/211/67 79/194/67 77/212/67 +f 69/189/68 65/213/68 77/214/68 79/215/68 +f 67/181/69 71/216/69 80/217/69 78/218/69 +f 65/177/70 67/219/70 78/220/70 77/212/70 +o Cube.005 +v -0.943184 0.837558 -2.455390 +v -1.036841 1.439106 -3.049282 +v -0.792203 0.083860 -3.242615 +v -0.885859 0.685407 -3.836507 +v 0.139915 1.029677 -2.431600 +v 0.046259 1.631224 -3.025491 +v 0.290897 0.275978 -3.218825 +v 0.197240 0.877526 -3.812716 +v -0.555839 1.663841 -3.864197 +v -0.540741 1.588471 -3.942919 +v -0.447529 1.683053 -3.861818 +v -0.432431 1.607683 -3.940540 +v -0.174641 -1.858866 -0.194089 +v -0.115495 -2.154119 -0.502475 +v 0.249651 -1.783606 -0.184769 +v 0.308796 -2.078859 -0.493156 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vn -0.9844 -0.1746 -0.0216 +vn 0.1372 -0.6850 -0.7155 +vn 0.9844 0.1746 0.0216 +vn -0.1372 0.6850 0.7155 +vn 0.9904 0.1079 0.0867 +vn 0.0455 -0.1340 -0.9899 +vn -0.1101 0.7073 -0.6983 +vn 0.7286 0.5591 -0.3956 +vn -0.8589 0.2775 -0.4304 +vn -0.1758 0.9707 0.1639 +vn 0.1101 -0.7073 0.6983 +vn -0.1264 0.6160 0.7775 +vn 0.1469 -0.7480 -0.6472 +vn -0.9698 -0.2398 0.0436 +usemtl Material.005 +s off +f 81/221/71 82/222/71 84/223/71 83/224/71 +f 83/225/72 84/226/72 88/227/72 87/228/72 +f 87/229/73 88/230/73 86/231/73 85/232/73 +f 85/233/74 86/234/74 82/235/74 81/236/74 +f 87/229/75 85/237/75 95/238/75 96/239/75 +f 88/240/76 84/226/76 90/241/76 92/242/76 +f 92/243/77 90/244/77 89/245/77 91/246/77 +f 86/247/78 88/230/78 92/248/78 91/246/78 +f 84/249/79 82/222/79 89/245/79 90/250/79 +f 82/251/80 86/234/80 91/252/80 89/253/80 +f 94/254/81 96/255/81 95/238/81 93/256/81 +f 85/233/82 81/257/82 93/258/82 95/259/82 +f 83/225/83 87/260/83 96/261/83 94/262/83 +f 81/221/84 83/263/84 94/264/84 93/256/84 diff --git a/aliveai_threats/readme.txt b/aliveai_threats/readme.txt new file mode 100644 index 0000000..03f3c9f --- /dev/null +++ b/aliveai_threats/readme.txt @@ -0,0 +1 @@ +threates / evil npc for aliveai \ No newline at end of file diff --git a/aliveai_threats/sec.lua b/aliveai_threats/sec.lua new file mode 100644 index 0000000..e43d7b1 --- /dev/null +++ b/aliveai_threats/sec.lua @@ -0,0 +1,427 @@ +minetest.register_craft({ + output = "aliveai_threats:secam_off", + recipe = { + {"default:steel_ingot", "dye:black", "default:steel_ingot"}, + {"default:glass", "default:steel_ingot", "default:glass"}, + {"default:steel_ingot", "dye:black", "default:steel_ingot"}, + } +}) +minetest.register_craft({ + output = "aliveai_threats:landmine 2", + recipe = { + {"","default:coal_lump",""}, + {"default:steel_ingot","default:mese_crystal_fragment",""}, + {"","default:steel_ingot",""}, + } +}) +minetest.register_craft({ + output = "aliveai_threats:timed_bumb 2", + recipe = { + {"default:steel_ingot","default:coal_lump","default:steel_ingot"}, + {"default:steel_ingot","default:mese_crystal_fragment","default:steel_ingot"}, + {"","default:coal_lump",""}, + } +}) +minetest.register_craft({ + output = "aliveai_threats:timed_nitrobumb 4", + recipe = { + {"default:steel_ingot","default:coal_lump","default:steel_ingot"}, + {"default:steel_ingot","default:mese_crystal_fragment","default:steel_ingot"}, + {"default:ice","default:coal_lump","default:ice"}, + } +}) + + +minetest.register_node("aliveai_threats:secam_off", { + description = "Security cam", + tiles = {"aliveai_threats_cam2.png"}, + drawtype = "nodebox", + walkable=false, + groups = {dig_immediate = 3}, + sounds = default.node_sound_glass_defaults(), + 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 and secure") + end, +on_rightclick = function(pos, node, player, itemstack, pointed_thing) + minetest.set_node(pos, {name ="aliveai_threats:secam", param1 = node.param1, param2 = node.param2}) + minetest.get_meta(pos):set_string("team",aliveai.team(player)) + minetest.get_node_timer(pos):start(1) + minetest.sound_play("aliveai_threats_on", {pos=pos, gain = 1, max_hear_distance = 15}) +end, +}) + +minetest.register_node("aliveai_threats:secam", { + description = "Security cam", + tiles = { + { + name = "aliveai_threats_cam1.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0, + }, + }, + }, + drawtype = "nodebox", + walkable=false, + groups = {dig_immediate = 3,stone=1,not_in_creative_inventory=1}, + sounds = default.node_sound_glass_defaults(), + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + drop="aliveai_threats: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) + local t=minetest.get_meta(pos):get_string("team") + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 15)) do + local te=aliveai.team(ob) + if te~="" and te~="animal" and te~=t and aliveai.visiable(pos,ob:get_pos()) then + local v=ob:get_pos() + 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, "aliveai_threats:bullet1") + m:setvelocity(s) + m:setacceleration(s) + minetest.sound_play("aliveai_threats_bullet1", {pos=pos, gain = 1, max_hear_distance = 15}) + minetest.after((math.random(1,9)*0.1), function(pos,s) + local m=minetest.add_entity(pos, "aliveai_threats:bullet1") + m:get_luaentity().team=t + m:setvelocity(s) + m:setacceleration(s) + minetest.sound_play("aliveai_threats_bullet1", {pos=pos, gain = 1, max_hear_distance = 15}) + end, pos,s) + return true + end + end + return true + end, +}) + +minetest.register_entity("aliveai_threats:bullet1",{ + hp_max = 1, + physical = false, + weight = 5, + visual = "sprite", + visual_size = {x=0.1, y=0.1}, + textures = {"default_mese_block.png"}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, +on_step=function(self, dtime) + local pos=self.object:get_pos() + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + local t=aliveai.team(ob) + if t~="" and t~="animal" and t~=self.team then + aliveai.punchdmg(ob,3) + self.timer=2 + break + end + end + self.timer=self.timer+dtime + local n=minetest.get_node(self.object:get_pos()).name + if self.timer>1 or (n and minetest.registered_nodes[n].walkable) then aliveai.kill(self) end + end, + timer=0, + team="", +}) +if aliveai_nitroglycerine then +minetest.register_node("aliveai_threats:landmine_on", { + description = "Landmine", + tiles = {"aliveai_threats_c4_controller.png"}, + drawtype = "nodebox", + groups = {attached_node = 1,dig_immediate = 3,stone=1,not_in_creative_inventory=1}, + sounds = default.node_sound_glass_defaults(), + is_ground_content = false, + paramtype = "light", + drop="aliveai_threats:landmine", + node_box = {type="fixed", + fixed={{-0.3, -0.7, -0.3, 0.3, -0.6, 0.3}} + }, + on_blast=function(pos) + minetest.set_node(pos,{name="air"}) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + local en=ob:get_luaentity() + if en and en.aliveai then en.drop_dead_body=0 end + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=250}}) + end + if aliveai_nitroglycerine then + aliveai_nitroglycerine.explode(pos,{ + radius=2, + set="air", + }) + end + end, + on_timer=function(pos, elapsed) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + local en=ob:get_luaentity() + if en and en.aliveai then en.drop_dead_body=0 end + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=250}}) + aliveai_nitroglycerine.explode(pos,{ + radius=2, + set="air", + }) + end + return true + end, +}) + +minetest.register_node("aliveai_threats:landmine", { + description = "Landmine", + tiles = {"aliveai_threats_c4_controller.png"}, + drawtype = "nodebox", + groups = {attached_node = 1,dig_immediate = 3,stone=1,not_in_creative_inventory=0}, + sounds = default.node_sound_glass_defaults(), + is_ground_content = false, + paramtype = "light", + node_box = {type="fixed", + fixed={{-0.3, -0.5, -0.3, 0.3, -0.4, 0.3}} + }, + on_blast=function(pos) + minetest.set_node(pos,{name="air"}) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + local en=ob:get_luaentity() + if en and en.aliveai then en.drop_dead_body=0 end + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=250}}) + end + aliveai_nitroglycerine.explode(pos,{ + radius=2, + set="air", + }) + end, + on_rightclick = function(pos, node, player, itemstack, pointed_thing) + minetest.set_node(pos,{name="aliveai_threats:landmine_on"}) + minetest.after(3, function(pos) + minetest.get_node_timer(pos):start(1) + minetest.sound_play("aliveai_threats_on", {pos=pos, gain = 1, max_hear_distance = 7}) + end, pos) + end, +}) + + +minetest.register_node("aliveai_threats:timed_bumb", { + description = "Timed bomb", + tiles = {"aliveai_threats_c4_controller.png"}, + groups = {dig_immediate = 2,mesecon = 2,flammable = 5}, + sounds = default.node_sound_wood_defaults(), + on_blast=function(pos) + minetest.set_node(pos,{name="air"}) + minetest.after(0.1, function(pos) + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 5)) do + local en=ob:get_luaentity() + if en and en.aliveai then en.drop_dead_body=0 end + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=250}}) + end + aliveai_nitroglycerine.explode(pos,{radius=5,set="air"}) + end,pos) + end, + on_timer=function(pos, elapsed) + minetest.registered_nodes["aliveai_threats:timed_bumb"].on_blast(pos) + end, + on_rightclick = function(pos, node, player, itemstack, pointed_thing) + local meta=minetest.get_meta(pos) + if meta:get_int("b")==1 then return end + meta:set_int("b",1) + minetest.get_node_timer(pos):start(5) + minetest.sound_play("aliveai_threats_on", {pos=pos, gain = 1, max_hear_distance = 7}) + end, + mesecons = {effector = + {action_on=function(pos) + minetest.registered_nodes["aliveai_threats:timed_bumb"].on_rightclick(pos) + end + } + }, + on_burn = function(pos) + minetest.registered_nodes["aliveai_threats:timed_bumb"].on_rightclick(pos) + end, + on_ignite = function(pos, igniter) + minetest.registered_nodes["aliveai_threats:timed_bumb"].on_rightclick(pos) + end, +}) + +minetest.register_node("aliveai_threats:timed_nitrobumb", { + description = "Timed nitrobomb", + tiles = {"aliveai_threats_c4_controller.png^[colorize:#51ffe255"}, + groups = {dig_immediate = 2,mesecon = 2,flammable = 5}, + sounds = default.node_sound_wood_defaults(), + on_blast=function(pos) + minetest.set_node(pos,{name="air"}) + minetest.after(0.1, function(pos) + aliveai_nitroglycerine.crush(pos) + local radius=5 + aliveai_nitroglycerine.explode(pos,{ + radius=radius, + hurt=0, + place={"default:snowblock","default:ice","default:snowblock"}, + place_chance=2, + }) + for _, ob in ipairs(minetest.get_objects_inside_radius(pos, radius*2)) do + local pos2=ob:get_pos() + local d=math.max(1,vector.distance(pos,pos2)) + local dmg=(8/d)*radius + local en=ob:get_luaentity() + if ob:is_player() or not (en and en.name=="aliveai_nitroglycerine:ice" or en.aliveai_ice) then + if ob:get_hp()<=dmg+5 then + aliveai_nitroglycerine.freeze(ob) + else + ob:punch(ob,1,{full_punch_interval=1,damage_groups={fleshy=dmg}}) + end + end + end + end,pos) + end, + on_timer=function(pos, elapsed) + minetest.registered_nodes["aliveai_threats:timed_nitrobumb"].on_blast(pos) + end, + on_rightclick = function(pos, node, player, itemstack, pointed_thing) + local meta=minetest.get_meta(pos) + if meta:get_int("b")==1 then return end + meta:set_int("b",1) + minetest.get_node_timer(pos):start(5) + minetest.sound_play("aliveai_threats_on", {pos=pos, gain = 1, max_hear_distance = 7}) + end, + mesecons = {effector = + {action_on=function(pos) + minetest.registered_nodes["aliveai_threats:timed_nitrobumb"].on_rightclick(pos) + end + } + }, + on_burn = function(pos) + minetest.registered_nodes["aliveai_threats:timed_nitrobumb"].on_rightclick(pos) + end, + on_ignite = function(pos, igniter) + minetest.registered_nodes["aliveai_threats:timed_nitrobumb"].on_rightclick(pos) + end, +}) + +end + +if aliveai_nitroglycerine then + +minetest.register_craft({ + output = "aliveai_threats:secam2_off 3", + recipe = { + {"default:diamond","aliveai_threats:secam_off", "default:ice"}, + } +}) + +minetest.register_node("aliveai_threats:secam2_off", { + description = "Nitro security cam", + tiles = {"aliveai_threats_cam2.png^[colorize:#51ffe255"}, + drawtype = "nodebox", + walkable=false, + groups = {dig_immediate = 3}, + sounds = default.node_sound_glass_defaults(), + 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 and secure") + end, +on_rightclick = function(pos, node, player, itemstack, pointed_thing) + minetest.set_node(pos, {name ="aliveai_threats:secam2", param1 = node.param1, param2 = node.param2}) + minetest.get_meta(pos):set_string("team",aliveai.team(player)) + minetest.get_node_timer(pos):start(1) + minetest.sound_play("aliveai_threats_on", {pos=pos, gain = 1, max_hear_distance = 15}) +end, +}) + +minetest.register_node("aliveai_threats:secam2", { + description = "Security cam", + tiles = { + { + name = "aliveai_threats_cam1.png^[colorize:#51ffe255", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 3.0, + }, + }, + }, + drawtype = "nodebox", + walkable=false, + groups = {dig_immediate = 3,stone=1,not_in_creative_inventory=1}, + sounds = default.node_sound_glass_defaults(), + is_ground_content = false, + paramtype = "light", + paramtype2 = "facedir", + drop="aliveai_threats:secam2_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) + local t=minetest.get_meta(pos):get_string("team") + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 15)) do + local te=aliveai.team(ob) + if te~="" and te~="animal" and te~=t and aliveai.visiable(pos,ob:get_pos()) then + local v=ob:get_pos() + 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, "aliveai_threats:bullet2") + m:get_luaentity().team=t + m:setvelocity(s) + m:setacceleration(s) + minetest.sound_play("aliveai_threats_bullet1", {pos=pos, gain = 1, max_hear_distance = 15}) + return true + end + end + return true + end, +}) + +minetest.register_entity("aliveai_threats:bullet2",{ + hp_max = 1, + physical = false, + weight = 5, + visual = "sprite", + visual_size = {x=0.1, y=0.1}, + textures = {"default_mese_block.png^[colorize:#51ffe2ff"}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, +on_step=function(self, dtime) + local pos=self.object:get_pos() + for i, ob in pairs(minetest.get_objects_inside_radius(pos, 2)) do + local t=aliveai.team(ob) + if t~="" and t~="animal" and t~=self.team then + if aliveai.gethp(ob)<=5 then + if ob:get_luaentity() then ob:get_luaentity().destroy=1 end + minetest.after(0.1, function(ob) + aliveai_nitroglycerine.freeze(ob) + end,ob) + else + aliveai.punchdmg(ob,5) + end + self.timer=2 + break + end + + end + self.timer=self.timer+dtime + local n=minetest.get_node(self.object:get_pos()).name + if self.timer>1 or (n and minetest.registered_nodes[n].walkable) then aliveai.kill(self) end + end, + timer=0, + team="" +}) +end diff --git a/aliveai_threats/sounds/aliveai_threats_bullet1.ogg b/aliveai_threats/sounds/aliveai_threats_bullet1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..18741d93c70ce834765e9f25aead7c6b6131f4f6 GIT binary patch literal 12120 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 literal 0 HcmV?d00001 diff --git a/aliveai_threats/sounds/aliveai_threats_on.ogg b/aliveai_threats/sounds/aliveai_threats_on.ogg new file mode 100644 index 0000000000000000000000000000000000000000..2d92d5ec11e07b575442abf9f6fb0b27e3b37e8d GIT binary patch literal 13304 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 literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_c4.png b/aliveai_threats/textures/aliveai_threats_c4.png new file mode 100644 index 0000000000000000000000000000000000000000..cf718bd21ac0fd3513d750dd5f122c01199c53c4 GIT binary patch literal 3800 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 literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_cam1.png b/aliveai_threats/textures/aliveai_threats_cam1.png new file mode 100644 index 0000000000000000000000000000000000000000..70ceba181f273ae0ea43011617523b796ba38dca GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^0zj<5!3HFyJAa%3QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XBj({-ZRBb+Kpdee4x4R3&e-K=-cll(X2z!aAuPgg~9zlK+ zZdKnckAXsSJzX3_JiL>?eE9I=yaQtbOVTNx1y@*o0%qknY-GH`-z;lg*6{MijR*r? z=5BF)w#yD*6QtNQ_?Zg}3)v*p#1vj9R{i{>%FH9oJ>lyE9_APZTb_*RLN{;Tlr(!| zc|_nr((wjA5L~c#`DCC7dx@v7EBk#OL4Ff% zRo^X-fkJhjE{-7<{>fiHeE4zRfiZz4=@id`E37^NvvM3ZGG5_tmbETxczNSSgaI#e zx41srWrwc`QfwOh%!P%8Y!Yf>3a=BZetuGA<`L$e@bv)?a}0wmPsVhin>TMtnytBY zN)VYJ0Q)iaJGfPkJ(|{Ap<*yM5}}Z28ODcX1}*ubBY07!r<>&pI+iG^EG*gi&kK2S(DGbEzKIX^cyHLnE7WngeFN=+BR}G>wloL#&zAr3uTErtJCr@m*y~OVM`97v zkJZ<-liqI6t^QGVPBEP6pH5wqfhOa;uH#M-Z#UnIdHHWj%g;`h9Io#S20YE--Up(% zl`d&38aK}@W$0Se(D8!Nz_`PMeSywtf&Cp%*l!#SwF(Fgy-_XNQ2kIu)nxs;+q>2^ zzlb}K8u>}~==XQO_toG2yPSbPIAhkc2Xkf`o-f|_I>P19pCvUL8QMj5tz#B!)l{0X z?Bo&_3x_w=`*z1)H@&_1ip6sqhMvb93^%svzG|&y<_~k?Jn47o4Je>IUHx3vIVCg! E0Caq#e*gdg literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_crystal_grass.png b/aliveai_threats/textures/aliveai_threats_crystal_grass.png new file mode 100644 index 0000000000000000000000000000000000000000..64642e19b7c839165b5b47d491ee82a4d783dd5a GIT binary patch literal 271 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DinK$vl=HlH+5kiEpy*OmP~w-m3b8PjaHGeDs^o-U3d7N@UHa^yR#z{4`VCawDA z)IBPXT>mEgTJV&%8vSEU~4Pj+Fr@o}cB=Y*E7 zWd+AFH>z+vU%J!U$CI<5$Mac3z?9MnbEd29t8n@JMQ^3}>hgbYmt{MuXlj?VO}wHt zZ)Gw&v&Df;nm0IpZ)37Q#ChRpR~oCR?g5(Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!T00ksTL_t(&L#3G8kt0PAMVkq10#k4RFZjk1 ztl<}j7H-F!;?(UdX;@B#wkuyZv${)Kjehv)`sLg8o&0(Ic73oo;aJw#x&D0peqEU$ zuW#31_p5Duy(aJ80;;#-KeTN+c5fj}#jIfxz6D+-Ll|M^jmD##1dAFsNX~r|Z_g)jy1Tmt;`kq*2UD@> z+$BJ=*XHDZdz2^Wp6m7)A!}^bw$1ny!fE8-X_vsXh4}2Brr5UNKqt2t+#e_%z_ws$ zJ3Jm^GsWy1A0xr`O*z|Bh?4+VjJ0!a0V_AeS{TN2&_yn8p15~_tO=&#PM(CPqEB>p(c6OLu=hU+Ld(^S(mYXTP}VG<4G<(izwdm+vi3;2lRKi%PL{DEoTC@$oSl`==?syoCr&O>Th>vbGSk$no6>lURJ%n}7?G z(A_5c!)m#@Q^4*#uInDa)Freqe6*_hitnDFowix`WFfxwUYKxEguI=sbKTxdU%|!U zF@b}@U7N(#QHCiIUkVVU(GqYlOm;|7)`)KBz?}ki$eLoaCYXxdDNMra9JKPu?naNB z2u|$czJ1Cg24m<8yJi z1rkhv7qIRkbAQ1gp}U7uXSly3z2X!{c-;fziJG2r6L__ifX`Fi_kchrOoA>B+c%UB zLKoW}?}0gW4v8HFD1_MU3rpZMJ|x~bx6OZ9{8xoNy&Pk`eWabH=+T{bZ@~$y?VH9A z$$8v^S5r)}$5U|U5ZlEq@(^$$VpC_>1l+wR2~6YI62Qr|yT%_Me)5i6aF>RhT<>!* zC6g3-DyGSG3An(tcncpNV;7plR-ALq+3xp3+wFh+h5~e8uh91TyODtRI28ly?H)J* z;^SoyKHkK@I#>J6@gTve5H-!*K z7$=1(Cu|cqiLQqD7UNvMdk!z6b6udO=< zd}h6!P5Ufn!LZ$fBu>R$1o6MTiGc9bU=yG?S6(NGjlU~5BoniJPcRk1sTdyjz$7_^ zuNo|YRyK~c*fznbQ~Pb-0*nf=PZQxM|K&ZHChA7(d!k?Q_50pFUmp{sgU6(!ecs;q zk>&(^O>*v-NA!68YCrbzF`m}J_TwHfzV{r~$e$1&|6*|w^b{fSmp=;!cb*!ox3jyM z?%ekFyYe(y$YA<4|K~M5_g_ d+*xiOhH0f@sx>D>-vCWz@O1TaS?83{1OWX6KAQjl literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_eyes_mad.png b/aliveai_threats/textures/aliveai_threats_eyes_mad.png new file mode 100644 index 0000000000000000000000000000000000000000..b4fdcaa3e7814df8533949e552d124813fc6c96a GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_r*vAk26?e?M;L2^K u`swQzUt|j3;Mt^lgWDl=pOVu4>x{8?1@9L=;dckx!rp44#i}+x@=~QS-zJ!cZDPL7 z^reqq_Dk)5L45`dC6DR@-}IhaD4p<&dA&wQ?|IBqhWs86B_#$(-j_p0lP)2)e$^%HDIgWr^Wk`&BjTbd?#IGG?(goV@pRSK7wa nIui<20v_7?|NN3})vJE){+r#BixbL$K49>4^>bP0l+XkKJrr~k literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_fangs2.png b/aliveai_threats/textures/aliveai_threats_fangs2.png new file mode 100644 index 0000000000000000000000000000000000000000..b4f4e1ece538ad777b4125ca149ddc1c351cd3a5 GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DinK$vl=HlH+5kiEpy*OmP~HwUi-fBO<{d!Wz)PZ!4!i_?22-{oyK;Awd;AY96M zgXLJ_oR*m{c;e-yq7Kb>nXqHJ_oE+4*4s*i=ZQP)blA9gZB^;9t0z`7J%5w8HT~`H ze^a&>DeP-yNbs?_d9zM}P3%U8LZ<*z@}up(9F3ZWA0B^sVc#mTSY>6V)ZRCT7j4O1 zEwMP~beWvv_0q@}*>U%7`X(Nmd0-Qp!!?hX_sZ$_UrZ8Q(a+P*dpWm;;r6x@9Jaq+ RFazDn;OXk;vd$@?2>=^jYODYN literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_gassman.png b/aliveai_threats/textures/aliveai_threats_gassman.png new file mode 100644 index 0000000000000000000000000000000000000000..8ae1432f10f891fed1a9ef814c276fff06a21f3e GIT binary patch literal 790 zcmV+x1L^#UP)P#n2E%g~XGfpha!0ZF&x=(a@M*n%rGA&6{5C+5$z4FxLyYVh1mMhc7@*{Hy%1^! zAnOjR0PKA;L(6XH>4fgdaRB0hE@BDDrQpTR`dUw^nOx-xu+(}wA(nv1yDk7)5`}A# z)GCT#xkT+qeoz@95-qHDaIBBuSRc6*M52Y*YH5ID_VmYNve_)Ut`iIfF${xrI*qET zc)eZ@c}_I;9FR;Vi@sqP_zB z6OGRkjnC72#LesIM&ftdEIA%qX_i;OzFq48xPECpxjD1w@91zzOZ`_n{OQ|mid_$$ zdX?wllZB<;&lkZ|bG&x)&9ZF(o=xS8el$MM#p7-iMO0k*aez&b1Z} z?k}wR`C}e?mHuC>fNBzVWDbx4uxk=q$*Hhh8#q-J%Z|fNo8RxZ_4)n%{S^nHpHHj@ UNk(^qZ~y=R07*qoM6N<$f}DD3Z~y=R literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_gassman2.png b/aliveai_threats/textures/aliveai_threats_gassman2.png new file mode 100644 index 0000000000000000000000000000000000000000..60a39bab65fec447da955caeeeb6e1d39652baaa GIT binary patch literal 738 zcmV<80v-K{P)JN6HySyKQD>4D@u_K8(kVis-%Uq*U}R3=3!4tdhrj)$x{v@z8&v zAoi3T(nGXY36`9js|O)OyAVh(R;p&av6ZS_*+k9bQ-g~?AnD3jNnSDw`@Pbmx z`+*S<5#{&YpnH#l7}p$A0(^yaV@?4B5r8qnwm!4w&YEYe0ZB<_7AQ4dO$h zusKw0+a7DqkEk&n`mYM8)#IU2p;nJWOJ25ZQ!bYQ*x1+r=o{O%9jprYCBV~Yhy-M_ zSvs8#j^nVlwg$k#!2yP0pzAu#W;2legm30NA|Pxyj)P$sbh}*u48y>29CTd|Y&#Jo z0sc!u6wYTd8CNeBivVnIZ=>rvnM@{d1o-*{E)uz1j#MgzWmz;D4NTJ{olaA$)i^pj zqF%3G?LJ^}anaRH)1=*Q4_v#l5de_S=K-)R3xHa!20*1!2~NOSJ?$$yqsmf{^`Q3$ zg+jsez~<-Y`^KA_n`+t$PYIY3aIs0yOe(&0g!8M0TeAvn208;8#GpB26h`HM(0^R+ zCzVu7n!I>=!=2lCJuB6cCU@^B346a$A|iN6=mb%EyxBQLo6%hT>-XM7o_-=K!z+(tJbU#6fW1#ME-}}Jfc53Lt3Q7d=iLYR?Sq3s zWirgt85sdD-~QzD;Y|SEfBZGEjZh*= literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_i.png b/aliveai_threats/textures/aliveai_threats_i.png new file mode 100644 index 0000000000000000000000000000000000000000..7e79bf3be4cd7ba6b59499829c8d1ba6e69db0d6 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blwj^(N7l!{JxM1({$v_d#0*}aI z1_r((Aj~*bn@<`j$X?><>&pI+iJL>$@bIg>-9RC3PZ!4!j_b(@3``6RtPG5g)L3T& Pg&90u{an^LB{Ts5c{Chz literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_mind_manipulator.png b/aliveai_threats/textures/aliveai_threats_mind_manipulator.png new file mode 100644 index 0000000000000000000000000000000000000000..ce34749064cabdaefbbeda70d2cb46c552990edc GIT binary patch literal 514 zcmV+d0{#7oP)9SXvl-yQ$}03B&m zSad^gZEa<4bN~PV002XBWnpw>WFU8GbZ8()Nlj2>E@cM*00Cx6L_t(o!|j*djf5}^ zgvaU36hlwD#Xuof%-jPBav%vN!0~dHkXHGdFV1=h0)Qk1FNBC7kQ5Q&8{#Apu%zHm zA(A+N1z-#D1dNF6#4~^lg5#|aB7(SPCcXnm;yV1`E{G&<*31Wx%pL#)N2)5pk+Dk9 z^DF`*R2AS@)~igs4B-*40$hdgiZ=mzA&0-S|7EA9gDLiC8QPIwd~1@c{f;{%de ziKhA{KC$8JuTyshmR(a-nIg8Y<5V>>n%gpv7E3V~;rHdJC=^)sBYvG)P zZ~>eVCn@m~v&(?0%Cra;ssI20 literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_natural_monster.png b/aliveai_threats/textures/aliveai_threats_natural_monster.png new file mode 100644 index 0000000000000000000000000000000000000000..2430f28652759a1dd89876cec6aea4bee4d0b948 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DjSL74G){)!Z!AbW|YuPggQCMjVF<*Y45azG(hPZ!4!i_^(}{{OdUR&D5PbTatB zwn3p-LQ?V})n!`u-)VCVV3LFv6$N?l5vAcbUpV4)5k)Gvl#SREqLY5a`Q0o X*h?xd3{8m#8pz=3>gTe~DWM4f{R1}0 literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_ninja.png b/aliveai_threats/textures/aliveai_threats_ninja.png new file mode 100644 index 0000000000000000000000000000000000000000..338de0bfebde4cab6ecec7b9de6224dd54ef110f GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQfx`y?k)`fL2$v|<&%LToCO|{ z#S9F5M?jcysy3fAP>{XE)7O>#Arm(TmrTru;MqW-c25__kc@k8Z=B|AaNu#h=&~m5 zl)#(%bmp)G){P9Uk$W^g@63Pd=FaEIv+JtxvZJllS2wSIu5VU(?cDwQSJ{2y8TT{9 z98W8JcXwLAY3B)I39)~a>$!V?Q*4Fdm+?2Z|5x>_Lv ziiMuHm1>SYL_t!G%jmjcMuNz~n z+-P)C0Z=>6wGu}kcR&hjeYC(uee9J)(K)SHgJt-svB4T~r58kTM;PZVMdsEwk8)}+ zZX!?DslA3Jq5_ip=;;~0|8NK2{?edK1b+YGPki(D0vE53JzJwd1okdPCv_Xl!rGoD zypT!Xe>0ulZiJf++8_xVZ5&$J_wLSaC#1C0`(MQ)^&9is#8|`*8ahLrjvGAgczRBoB8UKXR+adNjx(w5)6`B=8#Y; zfx|1{pV?-+$iQc-lyrRpP|`NGpI~KIEL3)q^B!?G@p5*7@PtJEMsY$lkF>Wh2gC=7 z7XbNG;04~|yZK(2t+i9+$R_*u;^*I1<&!Jq+cQiq`{&HI_}R_GQE)RQfd^;SG%}9?{t8%_bQ@_wuOU1%wgR zyqo^{RG>O{4k6M$O0=lA1!moW?yVl30k4mNR+@QZTi<*isNSEb>+RWKCeXEK$F7gizgeyL!ZZmdE_YI%esm9k5i%quPTUOOC%hpLxJ~Yc)VkogYqW zXUio#g7jo41JLlq65(@$(Aff0iM(9~yT$Gaa6R)lYp4Xa%!1BFr9KeK$xefj3d?wM zK6XaPf#4#g80%*bufkDf^Apf~UANxph3lCiQ{JsM6G9VV)Eh14MU1kd^^M|3*CD4S zm(sL8qt>oxo>Tl8TEhV5IL)8spwP8Trt1OF%56}DtT~=86T7~R^j+$*8TVk6OPG3f zoiR0>3abox&yRJd5I1bD1nG}Q=uB|_lnCkqx0i?7S1Rn|DFDS-0`DH9K8UwDuZ%8x z)#paG=pfJX1&rfJzVDX`y-4JQc!4^QE2%>* z+|8`D8IV5&@Gy{4Q{l6E@{()B9Ky4KDz@bP~6ww0+ zAyue_14N2S&IrK))H^CFC?^C;`XQAz30 z_ud;D7&5N^dM5?|MA{D)yN}qrNd5iHYcCqu=a75T9u`oVbWp1YC{1UtM%YAbPoY*1 zP%eas?J2zZ^3j3&=Y~olHkQg+y+11#LI8l*w$*v#7*Tqy)q|d&B=2qbtp=(S2JYq! zER3*pZchSO>9gMrP@OQO!d}~!Mi|==Ml2UXcx@YgH&MPiVZeI=oH?<7bnVRmnjuIK zuWcs++QR#xjd2gZ6Tt5PKw@wJSZ~E}^W#}Rx8I4b>7ZN)vEGV-$mtyh2UVVVe7zMX zdx>XYJZLlbD-?Nx6!*Kq*c9hR=KF92jBA(&^-j-WjfVjJZU8s$;Qt)ML%>qwpS;2i z;I(bIrXZ^^@_=hP@H?py)?17O$Fz^342&&RC}m+5>-3G^4YCHZp#0`{1I2^# zo#r_{Zy5jdQ;@u`5VV!1Yy|;cXu}I_X+b^;Gm)HFcs@#n6kd{W%R6xMj>z9aVR2QI zFw*&M>?nC(8d#ujwwUe@3z#eA;7kUpLPA05#I~Jqh%k1!5K4n`W0^c}OGC8nq_Pu6 zD9l7??^yEpt=euTP9*|5fm~b<2mX$fCV^ekQA5B=(Puh2oIExs_dj`T4yKb+_9q3U z?0j8bq-n-7`w^221);Fazd|U9fL^iKCk+w`s9^HDfz0WCH%L&y<6aM)Sh7X`*l; zxb|(cDHDmc$b$+`St_}49vBoNnQrQ*KOV$sdznpd!#c3*zubvwPQ@)^#sO}7ff`zz zrSpzdWR(8>=e0lMyLkf(#w3ieDd*7`Hh-i_aKmpLtb!BJo^gPk0P@g6fvS~;i`vr< z9jyD{K{2nxzv33L;WyMn2-A^X zqD?a`Fe6X;_M!0<&W;7Y8_0G0wZ5fk2lwJ90DuK!awrn$UYCQ2`rIoo4L%dptxgE2 z)su8X9hmNYVp2Mcl*WjF`$vHJN02;#;4uE0+lBQo4KYrx--iFB3qMP5mk!M<3N09u zsd4Nn+>4*!cqdN6$5s(E)yR(&QYMc}y62vDO(&zg5jN$iYptFhgp{ToJU9Y;dFc|a z86Il&0JpsW?|$<+KD&4k@e7ADnMF}v8(%!TuP8)Ueor!x@}vhR-k}H}W%&d;TGk7s z7_6v36XgOcqS^tjesT%htE<>vUB%MY7H;}J?q9hA0QeNZg?HZH^Pz}rU+dY7q03*Z zr+r6m#vGjlX+h-#w(UrmOHa3h%;_&b5pJxlCD3vlT)2E$`L40HmVy5$W4#qiBXG|) ziycfg@>1#CjG6F89V73N(>+hh_sRmijO9XcV}14Y5BSXu@%`1S*j!!)031Dg7H^+F zj}uRJC8y}TvUF%(LjJTpD?@|!;0V;ig1kM|$YZ0+GFD?m1IQB`ankFzlJt^ffe>XR zim$fV{ERhU~^>!H@CNC>Z8;}-s4QK zkJI)nsuPA{Y);lZ?gw$ha0GOMk%}Dd4Ke~hUvnAf{Cneuyx&}2M)kc9q+!=vF>*5< zndg@rV0swq;_&H^b z>O=^1V#FeMbNDNDfG|wC5CUN+t3KVcgScUM2vF-9rLf^O06~^-%88QK06GlM8M8QN z%qnTLH0>y%Qkr(~@sUbKF#Vm^wlf~>m%{Zh8Hj+=WbY3vZZX5w`XL8F)A#!$fds3# zMIdZq!*9rY{>{>%c?HILW|E%PI=-Y{LBEwj8>BECdcZ5uq5x!&b)auy8=3N=+L1E&dReTvm^AP&Kn9@fqtkrakd3Lg6dp#XqG9A?Zh_{zmK zE-S$|5pgcurr^o3Fc28^CE}rvc<2NB^Nc1d4S2xX*;j&!q%gm#@XRwg&!5|ntqb_d zHNjHwA4QFTFc3&mjZt43xlR_@K^5LVSl+j1beU^oS7{H=FWa*fKx03X^-2$*nz!X2 z4}DA)8Ag2x0GMrZgn=+wA_t75S>Qwzjs5+!g}iZ*q}teRBA(__8j@wj(V33PA! zv6}Ay06%qkv?n+ZccQFGIMv1>YG~X+%9hezr3Q@?FMuc<=;&ZtEFEaKL~^MsD&vTU zK9;$zlmS=7YQDpG+^di?oxbAw%cUX0R!}6x$)@P?x}8yWRYPt-yxE9#eS#>q6sAw`VA>qzeTNf4UB5}%tN9Lt+lyMyI(2Y!X+fGu3;N2%Y?DK252LJ7V6ntA7Ai`puH&&%BH>U6?b6omr(lfK?<{*J%aNM~U~I0e%J`=J}%37^x|?1>Y1%Bt@-M z=%PbTQ(vGRsOjv`)*H_H8jP-*2hzUGJ1RdRl2efsNN`#S@z6KDfbQ)v<8iN2!%YO* lXa8lcq2SesI7j{f@E0-9a3S`^R}BCF002ovPDHLkV1kh)`AGl( literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_quantum_monster.png b/aliveai_threats/textures/aliveai_threats_quantum_monster.png new file mode 100644 index 0000000000000000000000000000000000000000..c65f2e9e587b565e8ac0608a9528d8766239de5e GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQfx`y?k)`fL2$v|<&%LToCO|{ z#S9F5M?jcysy3fAP>{XE)7O>#ArrT-6;tLZky${Y>7Fi*AsP4HPCLliU?9Nq{fOD0 zUmJK1n(3TdRP$pilk|riht33(tTY7yr?|s!)s`8o%bpSEv+#@~1Cv~WWc1HFdxH+l zY+A(9d7ytIhw?go_ZE&PdJA}BXIzWR+k8g*>d}IVZ>csPty~}fuJ)S1=iu<=hITYCcAZUC^YbS{NqupP3vS}5@=vxQD9)?aA06EN@d=0(`s&PW6wOG6B#^R{an^L HB{Ts5O2A$R literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_quantum_monster_lights.png b/aliveai_threats/textures/aliveai_threats_quantum_monster_lights.png new file mode 100644 index 0000000000000000000000000000000000000000..f839fb73480b9cd5173e66aaeca10cd2427620b1 GIT binary patch literal 383 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DjSK$uZf!>a)($X?><>&pI+iCcuhDF5r5Qw$7@Jf1F&Ar_~XPBQFkcHnWH@2>rn ztz^nc!4rWQ)Al;eD!F3mFh#kgSRvPQ_M~Zg<~P{#1$~Y&pA^eJd8p@Y{(pOAR#jQk zy>bjUPR_Jd|FAWwI+#{UwLD>k=K2?_$}`L b8{;S4Z&6^~cVsOvs2Dt5{an^LB{Ts5GKZL` literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_quantumcore.png b/aliveai_threats/textures/aliveai_threats_quantumcore.png new file mode 100644 index 0000000000000000000000000000000000000000..508abbc63986901f6fc64a23e79235e9d55bcaed GIT binary patch literal 1744 zcmV;>1~2)EP)WFU8GbZ8()Nlj2>E@cM*00uNkL_t(o!|j(#j2%Z6 zhQD*F`f(p~=auoqkKi~?A}mZ~M?6dx2vEE-%R3wI*dQS!V23maHlV8rBo-hL8#V}m z#Ee9OM92aOMYa&(5dp$jNftP9Y>%UH#&_GKd!0vCbb0I%S9qj$FJA1J`;+WIlzO9V~;b3k5a!2kxp zI;{x=V1lv*d=tlyduO}le+00)wmt{+2s~S7VNrwRKI9hA%A|68ewr4MiN@gZCYyL$ z>ICI7@VVYf_uRh)u)4N>l)w*x!zgVhS?vWUM{14E8KiPCb(NQN zQrJ=lD81fF_dE9mu)4PX1c4vaS$IrDJEe3IX*rFF7i@#Fu|=>q@#faAHhuwH%wn9! z78dFdU0=ft14p2b^3~lSG-Dyo_ewrpkZK!t!+vGy{SH@MZyS zt3f?@mTYu@Y}Ce&LZql-BW^o&auem#y_N3I_5$!d0%v^AVkw=>%vdQpH)JyND~>*X zi4(NhM@oW)DS)G9lbSy>=HitZ(!m+poBQ#j5W}#Fjig`NQZM28NbhX7f2W?gOZ+JU zUqD$dY$rD}R?F75)Qd0h%wwB8!z_zrw6SCuQiK$tfuT*pAuMy9k~jV9RCz*p)lEY(@erQy|QUdD6J^WjIgIZ1~ZQd$I*F;1@U3}Hxv ziWySgN1Kl=N0@(ssy)JFm8hZ`BqQ+I)gP_5?g_BEw!TE*uyvYM%xcV>jAmZr$;UT1 zPLmu(sVHTOLT;c8cSb2&l(I!iL5}hyIqzRCDVncSwj5-sjHF}gEHp_ty;}rM082h4 z3&v`&2A}<&Q_`YAilN3!pTHPL%><<+r@-O}7z#@1lTy&ea*8JA;qyqMq|~?fTMm4D zH-M*6G)gokEeY1~(4lu|#Dp9OGMS18lqMz~gm{=3A0g6Vf)XeQGQk1~mVKQuRlbeS z5>%0?-tpZ4o~o0OmA<2DGkkK5g*=d8i3B1AmH;Rc7x5e*$`K6jLE{pFg{fbp#-i*a zC+G&XgnnD?l{F(9ej}z{Up{&2-fL^-6HTu0t5BpG}dTk z@uR2tZJaQmo{F^*QY-;wh-DMc_Eg+rXcK5Mq2@1)Dc?GY)*U47>?a4jd{2PhO7}W& z38<2B>7{DMY;=^1S6XZ`W=J5!7KRRn4k zw&HfMrA~lf?0yt0UnX!fiKUauk&b2wo2Pm4M&ugX45+DMgFMb-;vy!_W8yqE&Qrw} zLu#%v=B06gzj~The;KU;-p3d;Rw&=?t#n7b0`yk8uTE>bK{75~D681$AI80Xh8J%{ zUgaj+GGU8~F?MGRs2Nakk!@ZYl#KuONgDkph~*eJ(l}EOoGo<&_}1MiVgDsbl+P1* zIngp_j5;#Y;IP#0Q@pbA8h<@_j{S3e_LJ_^1DC1T7+Z#KeGpR~As;@36a`_Zu@$#H zK?;;F_Ex%Ed##9$5%?*}0Vi4Rnwix+N}U$e=@6fc@Y%J0EaD#~trifMl8$D<6}XAS zR@|=D$pqzVy_N1a?zbj;G+aS06YQ|zy*|Z mzi20000ejU6%j=1gJ?w zK~!koy;(ho8%GrWcF_eS4$fjBh1A3{xz;hbaFD9)LQrwWNfStM{S|IpyLRIuy}LAV zhz%m7NZ2$woX$xbgK(q81Qwsc=)g9Xi@i7g=IxAjPP>-@F+V#$?|tugMiFYty*bus zQ0`0+ZM#;^9*(D29?#79a6I*{Ssu^K{NZ?t@1ohp^W#urx}!8`tj#hUPc3FPG0gzg zfyAW~O3djZb27fOe`wlo|9ya+{X?s6QiLfN2+QM{L%U|Gt}pR6gq2%of@l(@;_?kGj)-E+gJmbmo4I(UVzZ><}d0o!+|dba`qtGl$NW({C1&>HaD zqdolkbJVIfv;{&fRdrE7`+zp1z>n+c#=<_@@b*KP7sk2I%(k5N z&x{Q>H3Qj4q|UXpH3)T*=5IWo8FT@n=kYfy6C5Vj@chY9C84?h-^c8(>{nyGjt0Zz z8c^7gff+aL7wwsw&wsFXU5Ov#q<>&QvH(~XPb+bpV>|%d{`3Lv&8yPZA#hndHDlTo ztp4S8eU3|muEdXVf&*Od{{dhZ{rA7)Qv4bx{R7(x`to;QXsgThc|VrEc7hk_gfG2( z1OVvo?c(LD*JixGw`+$%%_OV5i&tdXvfOdl00x%kW0svSn-vj~R0>POH>aghW z_EBi&sB;QVp;x(k{oQXj?|=8Fa{t}{SmkBiB=d~%KNSW;XOq1_l@VXzxuI)X1K@`| z`~hS*o>~lx)Qfp$5uZ#_tn%>3mF_4tbA4KLp3(_r{AiF#dwn#>B54DF^o^I#t2elk zaQktkHz)y-I`l0<_HRQ2Dyi@$Rdu}%X({vusNCQAGPBA{scS#LW5SsJ&LHW2Z(!eN z|@+@FVHs4$ZO)ceE!W8tGry#M9LZ&6Q)EoBXj?rTuQ zhJ{G2ioQFA4{Xq$lC4dMBbtcepJ$3owxE_;wl>@8XX5Pgt6VB0q+ai4i zM3`r=q;K;5Gw^vl*aXhE>n2~m(GDrKR zkT4l*^{cxEb9@(KMD2tSk%X3%*r+%|_UP;bd=hl^HE8F(#&<$(RsS)e9b=iyRO2;g zZK9^Ga46%9%RE7WG=i#&CYwdc`- z*yokCvtv!L?%$Kt{5S@)Gh<-cA?o<=GACa|+LW9%$^?Cv7++}P@S~;ayRo^lLEqe_ zrS5jv33>N-fgz~>^@~FO?78gf7d9aO{0-c=nVR{}JnKNuZ8vVV_eAe29{|S-lj*=G RMRfoG002ovPDHLkV1gI3i5~y} literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_stubborn_monster.png b/aliveai_threats/textures/aliveai_threats_stubborn_monster.png new file mode 100644 index 0000000000000000000000000000000000000000..4062477af19993e140a9e1e292bf2b693484a5a2 GIT binary patch literal 1312 zcmV+*1>gFKP)qscOI9~d_eDm#l^CvS2ewTUk-prf# z`+dLf&n6aP?7b!eWU$LESVw*LvvZ9A0KEM++;rIy@9tj+Yi0V!M0O6WrO^HI_bpulw050ns>#5m6GfH}K6#1^_<3vJe13(Ww9cUVHUgWMY!G zzOfttKy$_pkjD7EZdJ`)IDa+K{tD1nNd;+)d-LwkUF|%9&th5MH!8p` zSPJ-26cFc~D6i+`)l|O)Zrof72&e>32c;{m+XYK0#V%MOuUcw`v9 zzG4IG8_S_R`8A4AT9;#!BG`GN|0X!}dm-Tbo*$5}k4FK9eh+rRQZY{lSl?L2LfH)7 zqzaxJWWLaW=W5a^DrtyJmE9_&0w@f0-YGg2MH0^!{J@d~?s=&!d0+`PE>yS!V&!uP=ERa%)PDRc0P|*RS zJ#@0>5|-nrWNGrMR7K({K;Zgb7ko^Ipzs)v0+iiqs7i3q<$Mx}%V%kQzEJ~aYWmajdDA#aBP2aeU}Z>@-D-%SqEnerfhh~i zT#@A2ldviNQ3A)4pv)0bF)x#0R7p!4*T+Uc(W!*wJst(2M5psgl1?$IMn@5L(n_#@ zy5EUdK3se7;16{F{8s~XQu=WTFslBawAtHVew*!o0x!))to|KypWt`>=_iksfd2p> W6}&5iz{)=W0000N)nPl=wd?=8%+dhTTzMv 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 ALjV8( literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_stubborn_monster2.png b/aliveai_threats/textures/aliveai_threats_stubborn_monster2.png new file mode 100644 index 0000000000000000000000000000000000000000..025209ed644212b5e50045648545ca020c230bf1 GIT binary patch literal 1309 zcmV+&1>*XNP)GM;g(p4jiVTcO|2;D0QByCs1M0?ic^ zrX((Q(nntW;A7E$JoJ%sT&ca*T%G%F0;N-eTlMhHI*mElR;+KN!hpv^9{>bslAPlv zW&l@&$=XRIlLmMK%E9yT;&LC8-(E=M2Hd}+()&mmz*(R&pxG$EdisY{*^rhJ62|}z zm@7hMLs~&GZL!mi0cnEQ1wq;WlPknZn&-m+n5e5uZE6mWlNC&Ns`sjlI@CIVe^jRk z>YH*nMSOmS*23xnlM>YPkr;6D;+vxXaP77jKU}*VnE~@KCklgfK~YyVn$AlKprU5& z!}qirt<{$R09%{efmS$s`3iE5i;eXMfj%6i$}_n@5XIw^&XNMoUcMrN89lyMU&8UF z>%hwvc3<6JKmOG!@XZ9f+gBxpoI3Z)Oi(0c1_5`g9v+Q$aAL1ur188=3cACsdU6)v zDXmst5|!QV_El`7&^wVEL_IvC}(- zO7SlMz+UedP}#p%n!|LCk4a9n3r6Ll5Y>REbBX49 z0gKCh2^_Tqu-TaIX*LR?%4~f8jOg?Eok|~@?|u&esDJvR=mUUTaPZNWkESlbf7EaQ z|fM>$hV0-M#yl z_8+idOUh{eKAzdz^E&{5qFWYo7tY@dyMH19U64uq>`SXwqTd4an8C1%!LS=U@bvr+ zdVU9+tvv}mf#q${Eu-j`#a!I)97-uX9!(WYEQllAn&17>(asb2B$D*JkpXtr62RwS zK$vxcte%!tWBnGmb9Y4mRe{q(sik#0YYC>Vx20H8Hosv)zj~D#GsuH;6Rc5IVR>6k33O9hdH;PMHckZqT z8dDG)47=hX1d>40n#nqG0-UN4^}d7gB#DoQx&Z$e2hXW!XDtv@@=i(2b63#;qdRo8 z<`h=@LBY~wRh1QyvjBnX`5o{+J%Ze0Jer{BmZdDgnZvEGvuKpsLG7#T(52JFbpU@f z2ddJO*94>#6G(MFgyP!0v|jfrz(Pg;dOmOJM=69< zUcmBn?a7lr(E0OU4bWNYhXuf({D0J9Z+!7>vi}55*8*1m4jD)IU4QbqLsh_kvzo3A Tqn!Jf00000NkvXXu0mjf_6u}P literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_stubborn_monster3.png b/aliveai_threats/textures/aliveai_threats_stubborn_monster3.png new file mode 100644 index 0000000000000000000000000000000000000000..fb82cdbb5d4031a6f81149e76dd3f8c42f3bb9e9 GIT binary patch literal 1329 zcmV-11I# z>5rv!3dIqLm2sep!7_qmJ4<&_5XMCWM@*VWVx*J=pNq-4bMDQ(?`Phd!Lzx4@7;I4 zbH4KvVj)64T0npla-{`pzwcf@?F9hfciM1jp4j(0ZR0ym%@fc2op$8+=kPxkztfh$ zgn{M;iZT)xJFSxEKK@k9pNxFu3yw5iX|>= z00J~gzTl*005^om+i7Gj3-AP#gXimor2&H9UrH4QJig=7`%oFcS)ekY)hxk!_Qy=w zkd+Zq=Kv0v8$xA6R!K2yv9rzrS%TLkK{@`@8^lUm=c53asH-b&Y7I|P6-;-k_o|FK z&^~~FRA&g9n`$^^eEtrdMfC+HBdG7kV!-ip?}+)smD^(daOHMv2JDA9PR+9-7!>G| zqONN+F;Fr9H8m@re5kc(y|D-Y*jV2T^}?wO7m+VGSX+G%8pAQVJj)aUQwekwPtrO| z1~_%$qDW?>e7&)Vql;I8*DP$mv3q{>>ubQb0k$_UNd`G_`t_NlNX85U?$kUy8gE(0 zc1i&QYsIJlL7XINy2Gh?auwhut=?D^o!$24C2Zt9UV2Ip5!^4y^SL zegFV8K7ScB2LPv3z~!$VSt11Zj~WhuLct^|aMk-8>zl^X$Je@_ttudz#}P7=3fdox z%t;0SKD&An08lKH0RV5mbt_Q@zjy!qt^)J6WQ^7ylbL7xeis1XIu)^Z_RP&#_Y0u& zGKrsmCE2gfnLdD&8IF1wj(UkpSl{oW?{~4@-jTo)SU$Q=1+G&Odr7}@Ag%CZyq7nK z1xbW^^ZQ@B+I<3_M$*1-WPqKs1n~VZAj&&oUeC&_iGB;*xw|ZYs=!H68tL55S%N8c z&XT-(_RLLu(|-~F6o0}qLwS7D-i={?Cm+KMO6Tg_#0aiWCi)0rW0{mkf zJg1_avp`HK7Rq9uhl&mu-Jzp3r?5H?OO__Ds;r1z1qfW-telxd{wVK-#5+UG(xJ! z39K3tu2Yc=R4kNdSYXP+YOaX$>|w|p|0sduNl?uZVKJ{J!?2Q;G_DWK0L4OCqW5GR zNQqA8l{lSZSd9)d*kLol{`r@kkmJ3xr%(Sx_pg67Kxe5Rl>o!)|6z;0_T_i!{u6k$ n9&-A3#5%_B`r|Jgr~&>1Ek3vn?15XX00000NkvXXu0mjfLm+5^ literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_terminator.png b/aliveai_threats/textures/aliveai_threats_terminator.png new file mode 100644 index 0000000000000000000000000000000000000000..e9803dca41d2930c5e3faacbb07a0cb8cbf4699c GIT binary patch literal 1926 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 literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_testbottle.png b/aliveai_threats/textures/aliveai_threats_testbottle.png new file mode 100644 index 0000000000000000000000000000000000000000..04aa0e29c7709ab073c96fb4256b85460e3dec27 GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=BdgAk26#O}+vs$X?><>&pI+Lx4-2%S~wkP>vzk)5S5w;`G}|j$8*EIGB@fZh!Ls zexbdw?euGpHf_JuAU@e6fcXL+U+yD$h2E|i#c}77t)~g!=sWdep(@vo(6mc08H2(j n3UiB>MjF{?9>4v$q<~3L^Snu8(D{Wx;~6|%{an^LB{Ts5>=r_x literal 0 HcmV?d00001 diff --git a/aliveai_threats/textures/aliveai_threats_testbottle_containin.png b/aliveai_threats/textures/aliveai_threats_testbottle_containin.png new file mode 100644 index 0000000000000000000000000000000000000000..299748bb60d15bac8312c0f00641d57dca1d314f GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=BdgAk26#O}+vs$X?><>&pI+Lx7u$DN|5l9#AOR)5S5w;`G}|2RRQI@Gw8U5IJS1 zmD{qDF;|V=t)C#aowISzs`-XiEjh*IXEYLn>=|w>YF+ZoMkUvR(X+cJ+sZ)1TqJ(J z!=&_U+2_{u2RR?O`-j!j_L;fID^vFg&nEJ{J*+x!T7<#XucrfrfYvd1y85}Sb4q9e E01M7ZO8@`> literal 0 HcmV?d00001 diff --git a/aliveai_threats/tree.lua b/aliveai_threats/tree.lua new file mode 100644 index 0000000..e2ac451 --- /dev/null +++ b/aliveai_threats/tree.lua @@ -0,0 +1,210 @@ +aliveai_threats.spawn_tree=function(self) + if not (self and self.object) then return false end + local pos=aliveai.roundpos(self.object:getpos()) + if minetest.get_node(pos).name=="air" then return false end + + self.tree_by_nodes={} + local trunk="" + local leaves="" + local tree={} + local hight=1 + local g=0 + local gm=2 + local xx + local zz + + for x=-5,5,1 do + for z=-5,5,1 do + for y=0,15,1 do + local p={x=pos.x+x,y=pos.y+y,z=pos.z+z} + local name=minetest.get_node(p).name + local det=0 + if minetest.is_protected(p,"") then + return false + elseif aliveai.group(p,"leaves")>0 and (leaves=="" or name==leaves) then + det=1 + elseif (aliveai.group(p,"tree")>0 or name=="default:acacia_bush_stem" or name=="default:bush_stem") and (trunk=="" or name==trunk) then + det=2 + end + if det>0 then + xx=math.abs(x) + zz=math.abs(z) + if xx>g and xx<=gm then + g=xx + gm=g+1 + end + if zz>g and zz<=gm then + g=zz + gm=g+1 + end + if xxhight then hight=y end + end + end + end + end + end + + if #tree<2 then return false end + self.storge2=hight/2 + local c=self.object:get_properties().collisionbox + c[5]=self.storge2 + self.object:set_properties({collisionbox=c}) + if trunk~="" then + self.object:set_properties({textures={trunk}}) + self.storge1=trunk + else + self.storge1="default:tree" + end + + for _, d in ipairs(tree) do + if d[1]+d[2]+d[3]~=0 then + local e=minetest.add_entity(pos, "aliveai_threats:trees_block") + e:set_properties({textures={d[4]}}) + e:set_attach(self.object, "", {x=d[1]*30,y=d[2]*30,z=d[3]*30}, {x=0,y=0,z=0}) + e:get_luaentity().contenta=d[4] + table.insert(self.tree_by_nodes,{ob=e,pos={x=d[1],y=d[2],z=d[3]},it=d[4]}) + end + minetest.remove_node(d[5]) + end + return true +end + +aliveai_threats.load_tree=function(self) + if not (self and self.object) then return false end + local pos=aliveai.roundpos(self.object:getpos()) + self.tree_by_nodes={} + local c=self.object:get_properties().collisionbox + c[5]=self.storge2 + self.object:set_properties({textures={self.storge1},collisionbox=c}) + + for _, d in ipairs(self.tree_by_nodes_load) do + local e=minetest.add_entity(pos, "aliveai_threats:trees_block") + e:set_properties({textures={d[4]}}) + e:set_attach(self.object, "", {x=d[1]*30,y=d[2]*30,z=d[3]*30}, {x=0,y=0,z=0}) + e:get_luaentity().contenta=d[4] + table.insert(self.tree_by_nodes,{ob=e,pos={x=d[1],y=d[2],z=d[3]},it=d[4]}) + end + self.tree_by_nodes_load=nil + return true +end + +aliveai.savedata.trees=function(self) + if self.tree_by_nodes then + local dat="" + for _, d in ipairs(self.tree_by_nodes) do + if dat~="" then + dat=dat .. "!" + end + dat=dat .. d.pos.x .."#" .. d.pos.y .."#" .. d.pos.z .."#" .. d.it + end + return {tree_by_nodes=dat} + end +end + +aliveai.loaddata.trees=function(self,r) + if r.tree_by_nodes and type(r.tree_by_nodes)=="string" then + local dat={} + local a1=r.tree_by_nodes.split(r.tree_by_nodes,"!") + for _, d in ipairs(a1) do + local a2=d.split(d,"#") + local p=aliveai.strpos(a2[1] .."," .. a2[2] .."," .. a2[3],true) + table.insert(dat,{p.x,p.y,p.z,a2[4]}) + end + self.tree_by_nodes_load=dat + end + return self +end + + + +aliveai.create_bot({ + attack_players=1, + name="trees", + team="tree", + texture="default_tree.png", + talking=0, + light=0, + building=0, + type="monster", + hp=30, + dmg=9, + arm=2, + name_color="", + collisionbox={-0.5,-0.5,-0.5,0.5,3,0.5}, + visual="wielditem", + basey=-0.5, + drop_dead_body=0, + escape=0, + spawn_on={"group:tree","default:acacia_bush_stem","default:bush_stem"}, + spawn_y=0, + visual_size={x=0.5,y=0.5}, + smartfight=0, + check_spawn_space=0, + spawn_chance=500, + spawn=function(self) + if aliveai_threats.spawn_tree(self)==false then + self.object:remove() + return self + end + end, + on_load=function(self) + if not self.tree_by_nodes_load then + self.object:remove() + return self + end + aliveai_threats.load_tree(self) + end, + death=function(self,puncher,pos) + if self.tree_by_nodes then + for _, d in ipairs(self.tree_by_nodes) do + if d and d.ob then + d.ob:set_detach() + d.ob:setacceleration({x=0, y=-10, z=0}) + d.ob:setvelocity({x=math.random(-2,2), y=math.random(0,1), z=math.random(-2,2)}) + d.ob:set_pos({x=pos.x+d.pos.x,y=pos.y+d.pos.y,z=pos.z+d.pos.z}) + d.ob:set_properties({visual_size={x=0.65,y=0.65}}) + end + end + end + end, + on_punched=function(self,puncher) + end +}) + +minetest.register_entity("aliveai_threats:trees_block",{ + hp_max = 10, + physical =true, + pointable=true, + visual = "wielditem", + textures ={"air"}, + visual_size={x=2,y=2}, + on_activate=function(self, staticdata) + minetest.after(0.1, function(self) + if not self.object:get_attach() then + self.object:remove() + end + end,self) + self.endtime=math.random(1,4) + end, + on_step=function(self, dtime) + self.time=self.time+dtime + if self.time<2 then return self end + self.time=0 + if not self.object:get_attach() then + self.time2=self.time2+1 + if self.time2>self.endtime then + if math.random(1,2)==1 then + minetest.add_item(self.object:get_pos(),self.contenta):get_luaentity().age=890 + end + self.object:remove() + end + end + end, + endtime=1, + time=0, + time2=0, +}) \ No newline at end of file