415 lines
12 KiB
Lua
415 lines
12 KiB
Lua
aliveai_ants={max=20}
|
|
|
|
aliveai_ants.set_color=function(self)
|
|
local c=minetest.get_meta(self.home):get_string("color")
|
|
if c=="" then
|
|
aliveai_ants.gen_color(self)
|
|
c=minetest.get_meta(self.home):get_string("color")
|
|
end
|
|
local t="aliveai_ant.png^[colorize:#" .. c
|
|
self.object:set_properties({
|
|
textures = {t,t,t,t,t,t},
|
|
})
|
|
end
|
|
|
|
aliveai_ants.gen_color=function(self)
|
|
local pos=self.home
|
|
local c=""
|
|
local n=0
|
|
local t="0123456789ABCDEF"
|
|
for i=1,6,1 do
|
|
n=math.random(1,16)
|
|
c=c .. string.sub(t,n,n)
|
|
end
|
|
minetest.get_meta(pos):set_string("color",c .. "55")
|
|
end
|
|
|
|
aliveai_ants.gen_hill=function(self)
|
|
local count=0
|
|
local pos=self.home
|
|
local m=minetest.get_meta(pos)
|
|
local size=m:get_int("size")
|
|
local op={x=pos.x,y=pos.y,z=pos.z}
|
|
local s=1
|
|
local level=pos.y
|
|
local wall
|
|
local t=0
|
|
local path={}
|
|
|
|
for y=-size,size,1 do
|
|
for x=-size,size,1 do
|
|
for z=-size,size,1 do
|
|
local p={x=pos.x+x,y=pos.y+y,z=pos.z+z}
|
|
local node=minetest.registered_nodes[minetest.get_node(p).name]
|
|
if node and node.buildable_to and vector.length(vector.new(x,y,z))/size<=1 then
|
|
wall=true
|
|
if p.y==level and (
|
|
(y==0 and (x==0 or z==0)) or
|
|
(z==0 and (p.x==op.x+s or p.x==op.x+s+1)) or
|
|
(z==0 and (p.x==op.x-s or p.x==op.x-s-1)) or
|
|
(x==0 and (p.z==op.z+s or p.z==op.z+s+1)) or
|
|
(x==0 and (p.z==op.z-s or p.z==op.z-s-1))) then
|
|
wall=false
|
|
elseif p.y>level then
|
|
level=p.y
|
|
s=s+1
|
|
end
|
|
if wall then
|
|
t=t+0.01
|
|
minetest.after(t, function(p)
|
|
minetest.add_node(p,{name="aliveai_ants:anthill"})
|
|
end,p)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
aliveai.create_bot({
|
|
description="Little hill building ant\nEven its small its still a warrior, and will fight for possible matrelas and carry away everything even its still alive",
|
|
drop_dead_body=0,
|
|
attack_players=1,
|
|
name="ant",
|
|
team="bug",
|
|
texture={"aliveai_ant.png","aliveai_ant.png","aliveai_ant.png","aliveai_ant.png","aliveai_ant.png","aliveai_ant.png"},
|
|
attacking=1,
|
|
talking=0,
|
|
light=0,
|
|
building=0,
|
|
escape=0,
|
|
type="monster",
|
|
dmg=0,
|
|
hp=4,
|
|
name_color="",
|
|
arm=1,
|
|
smartfight=0,
|
|
spawn_on={"group:sand","group:spreading_dirt_type","default:gravel"},
|
|
attack_chance=2,
|
|
visual="cube",
|
|
visual_size={x=0.4,y=0.001},
|
|
collisionbox={-0.1,0,-0.1,0.2,0.3,0.2},
|
|
basey=0,
|
|
distance=10,
|
|
pickuping=0,
|
|
annoyed_by_staring=0,
|
|
on_load=function(self)
|
|
self.aliveai_ant=1
|
|
if self.home and minetest.get_node(self.home).name=="aliveai_ants:antbase" then
|
|
local m=minetest.get_meta(self.home)
|
|
self.antcolor=m:get_string("color")
|
|
self.antsize=m:get_int("size")
|
|
self.antcount=m:get_int("count")
|
|
self.team=m:get_string("team")
|
|
aliveai_ants.set_color(self)
|
|
end
|
|
end,
|
|
spawn=function(self)
|
|
self.aliveai_ant=1
|
|
local pos=aliveai.roundpos(self.object:get_pos())
|
|
self.home=pos
|
|
self.team=pos.x .."_" .. pos.y .. "_" .. pos.z
|
|
if minetest.get_node(pos).name=="aliveai_ants:antbase" then
|
|
self.home=pos
|
|
local m=minetest.get_meta(self.home)
|
|
self.antcolor=m:get_string("color")
|
|
self.antsize=m:get_int("size")
|
|
self.antcount=m:get_int("count")
|
|
self.team=m:get_string("team")
|
|
aliveai_ants.set_color(self)
|
|
local ss=m:get_int("size")
|
|
local ssrnd={x=math.random(-1,1)*ss,z=math.random(-1,1)*ss}
|
|
local ssp={x=self.home.x+ssrnd.x,y=self.home.y,z=self.home.z+ssrnd.z}
|
|
local p=aliveai.creatpath(self,self.home,ssp)
|
|
if p then
|
|
self.antdig=""
|
|
self.path=p
|
|
end
|
|
return self
|
|
end
|
|
local opos={x=pos.x,y=pos.y,z=pos.z}
|
|
for i=-1,-9,-1 do
|
|
local tn=minetest.registered_nodes[minetest.get_node({x=pos.x,y=pos.y+i,z=pos.z}).name]
|
|
if tn and tn.walkable and tn.buildable_to==false then
|
|
pos=opos
|
|
self.home=opos
|
|
break
|
|
elseif i==-9 then
|
|
--aliveai.punch(self,self.object,20)
|
|
return self
|
|
end
|
|
opos={x=pos.x,y=pos.y+i,z=pos.z}
|
|
end
|
|
local node=minetest.registered_nodes[minetest.get_node(pos).name]
|
|
if not node or node.buildable_to==false or minetest.is_protected(pos,"") then return self end
|
|
for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 20)) do
|
|
local en=ob:get_luaentity()
|
|
if en and en.aliveai_ant and aliveai.get_bot_name(ob)~=self.botname then return self end
|
|
end
|
|
minetest.set_node(pos,{name="aliveai_ants:antbase"})
|
|
self.home=pos
|
|
aliveai_ants.gen_color(self)
|
|
aliveai_ants.set_color(self)
|
|
local m=minetest.get_meta(pos)
|
|
m:set_string("team",self.team)
|
|
self.antcolor=m:get_string("color")
|
|
self.antsize=m:get_int("size")
|
|
self.antcount=m:get_int("count")
|
|
end,
|
|
on_step=function(self,dtime)
|
|
|
|
if self.path and math.random(1,20)==1 then
|
|
for _, ob in ipairs(minetest.get_objects_inside_radius(self.object:get_pos(), 1)) do
|
|
local en=ob:get_luaentity()
|
|
if en and en.aliveai_ant and aliveai.get_bot_name(ob)~=self.botname then
|
|
aliveai.jump(self)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if self.antdig and self.path then
|
|
aliveai.path(self)
|
|
if not self.path or self.done=="path" then
|
|
local n=aliveai.digdrop(self.antdig)
|
|
if n and n~="" then
|
|
self.fight=minetest.add_item(self.antdig, n.name .." ".. n.n)
|
|
minetest.set_node(self.antdig,{name="air"})
|
|
self.antdig=nil
|
|
end
|
|
else
|
|
return self
|
|
end
|
|
end
|
|
|
|
|
|
if self.carry and self.path then
|
|
aliveai.path(self)
|
|
if not self.path or self.done=="path" then
|
|
if self.done=="path" or aliveai.distance(self,self.home)<4 then
|
|
if minetest.get_node(self.home).name~="aliveai_ants:antbase" then
|
|
local opos={x=self.home.x,y=self.home.y,z=self.home.z}
|
|
for i=-1,-9,-1 do
|
|
local tn=minetest.registered_nodes[minetest.get_node({x=self.home.x,y=self.home.y+i,z=self.home.z}).name]
|
|
if tn and tn.walkable and tn.buildable_to==false then
|
|
self.home=opos
|
|
break
|
|
elseif i==-9 then
|
|
aliveai.punch(self,self.object,20)
|
|
return self
|
|
end
|
|
opos={x=self.home.x,y=self.home.y+i,z=self.home.z}
|
|
end
|
|
minetest.set_node(self.home,{name="aliveai_ants:antbase"})
|
|
local m=minetest.get_meta(self.home)
|
|
m:set_string("color",self.antcolor)
|
|
m:set_string("count",self.antcount)
|
|
m:set_string("size",self.antsize)
|
|
else
|
|
local m=minetest.get_meta(self.home)
|
|
local s=m:get_int("s")
|
|
local count=m:get_int("count")
|
|
for _, ob in ipairs(minetest.get_objects_inside_radius(self.home, 2)) do
|
|
if ob and ob:get_attach() then ob:set_detach() end
|
|
if not (ob:get_luaentity() and ob:get_luaentity().team==self.team) then
|
|
aliveai.punch(self,ob,10)
|
|
count=count+1
|
|
s=s+1
|
|
end
|
|
end
|
|
m:set_int("count",count)
|
|
if s>9 then
|
|
m:set_int("s",0)
|
|
m:set_int("size",m:get_int("size")+1)
|
|
aliveai_ants.gen_hill(self)
|
|
else
|
|
m:set_int("s",s)
|
|
end
|
|
local ss=m:get_int("size")
|
|
local ssrnd={x=math.random(-1,1)*ss,z=math.random(-1,1)*ss}
|
|
local ssp={x=self.home.x+ssrnd.x,y=self.home.y,z=self.home.z+ssrnd.z}
|
|
local p=aliveai.creatpath(self,self.home,ssp)
|
|
if p then
|
|
self.antdig=""
|
|
self.path=p
|
|
end
|
|
end
|
|
end
|
|
self.done=""
|
|
self.carry=nil
|
|
self.fight=nil
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
if self.fight and not self.fight:get_attach() and aliveai.distance(self,self.fight:get_pos())<=self.arm+2 then
|
|
if aliveai.gethp(self.fight)>6 then
|
|
aliveai.punch(self,self.fight,1)
|
|
elseif aliveai.gethp(self.fight)>0 and not self.fight:get_attach() then
|
|
local pos=self.object:get_pos()
|
|
local p=aliveai.creatpath(self,pos,aliveai.roundpos(self.home))
|
|
if p~=nil then
|
|
aliveai_ants.ant=self.object
|
|
aliveai_ants.carry=self.fight
|
|
local e=minetest.add_entity(pos, "aliveai_ants:antcarry")
|
|
self.fight:set_attach(e, "",{x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
|
|
self.carry=e
|
|
self.path=p
|
|
self.done=""
|
|
return self
|
|
end
|
|
end
|
|
else
|
|
if math.random(1,10)==1 then
|
|
local pos=self.object:get_pos()
|
|
for _, ob in ipairs(minetest.get_objects_inside_radius(pos, 5)) do
|
|
if ob and ob:get_luaentity() and not ob:get_attach() and ob:get_luaentity().name=="__builtin:item" then
|
|
self.fight=ob
|
|
self.temper=1
|
|
return self
|
|
end
|
|
end
|
|
|
|
local dg=minetest.find_node_near(aliveai.roundpos(pos), self.distance,{"group:choppy","group:snappy","group:flora","group:choppy","group:oddly_breakable_by_hand","group:leaves","aliveai_ants:antbase"})
|
|
if not dg or aliveai.samepos(dg,self.home) or minetest.is_protected(dg,"") or minetest.get_meta(dg):get_string("owner")~="" then return end
|
|
local p=aliveai.neartarget(self,dg,0,1,1)
|
|
if not p then return end
|
|
p=aliveai.creatpath(self,pos,p)
|
|
if not p then return end
|
|
self.path=p
|
|
self.antdig=dg
|
|
self.done=""
|
|
return self
|
|
else
|
|
aliveai.task_stay_at_home(self)
|
|
end
|
|
end
|
|
end,
|
|
click=function(self,clicker)
|
|
clicker:punch(self.object,1,{full_punch_interval=1,damage_groups={fleshy=2}})
|
|
end,
|
|
death=function(self,puncher,pos)
|
|
if not self.antcolor then self.antcolor="000000" 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 = 0.5,
|
|
texture = "default_dirt.png^[colorize:#" .. self.antcolor,
|
|
collisiondetection = true,
|
|
})
|
|
return self
|
|
end,
|
|
})
|
|
|
|
minetest.register_node("aliveai_ants:anthill", {
|
|
description = "Ant base",
|
|
tiles = {"aliveai_anthill.png"},
|
|
groups = {crumbly = 1, soil = 1,not_in_creative_inventory=1},
|
|
sounds = default.node_sound_dirt_defaults(),
|
|
})
|
|
|
|
minetest.register_node("aliveai_ants:antbase", {
|
|
description = "Ant base",
|
|
tiles = {"aliveai_ant_base.png"},
|
|
groups = {crumbly = 1, soil = 1,not_in_creative_inventory=1},
|
|
sounds = default.node_sound_dirt_defaults(),
|
|
paramtype="light",
|
|
drawtype="glasslike",
|
|
walkable=false,
|
|
on_timer = function (pos, elapsed)
|
|
local c=0
|
|
local ants=0
|
|
local meta=minetest.get_meta(pos)
|
|
local team=meta:get_string("team")
|
|
local count=meta:get_int("count")
|
|
for i in pairs(aliveai.active) do
|
|
c=c+1
|
|
if not aliveai.active[i] or not aliveai.active[i]:get_luaentity() or not aliveai.active[i]:get_hp() or aliveai.active[i]:get_hp()<=0 then
|
|
table.remove(aliveai.active,c)
|
|
c=c-1
|
|
elseif aliveai.active[i]:get_luaentity().aliveai_ant and aliveai.active[i]:get_luaentity().team==team then
|
|
ants=ants+1
|
|
if ants>=count or ants>aliveai_ants.max then return true end
|
|
end
|
|
end
|
|
local e=minetest.add_entity(pos,"aliveai_ants:ant")
|
|
return true
|
|
end,
|
|
on_construct = function(pos)
|
|
local m=minetest.get_meta(pos)
|
|
m:set_int("count",1)
|
|
minetest.get_node_timer(pos):start(10)
|
|
end,
|
|
})
|
|
|
|
aliveai.savedata.task_build=function(self)
|
|
if self.aliveai_ant then
|
|
return {aliveai_ant=1,team=self.team,antcolor=self.antcolor,antcount=self.antcount,antsize=self.antsize}
|
|
end
|
|
end
|
|
|
|
aliveai.loaddata.task_build=function(self,r)
|
|
if r.aliveai_ant then
|
|
self.aliveai_ant=1
|
|
self.team=r.team
|
|
self.antcolor=r.antcolor
|
|
self.antsize=r.antsize
|
|
self.antcount=r.antcount
|
|
end
|
|
return self
|
|
end
|
|
|
|
|
|
minetest.register_entity("aliveai_ants:antcarry",{
|
|
hp_max = 5,
|
|
physical =false,
|
|
weight = 5,
|
|
collisionbox = {-0.35,-0.35,-0.35,0.35,0.35,0.35},
|
|
visual = "cube",
|
|
visual_size = {x=1,y=1},
|
|
textures ={"aliveai_air.png","aliveai_air.png","aliveai_air.png","aliveai_air.png","aliveai_air.png","aliveai_air.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_activate=function(self, staticdata)
|
|
if not aliveai_ants.carry then self.object:remove() return end
|
|
self.carry=aliveai_ants.carry
|
|
self.ant=aliveai_ants.ant
|
|
aliveai_ants.carry=nil
|
|
aliveai_ants.ant=nil
|
|
return self
|
|
end,
|
|
on_step=function(self, dtime)
|
|
self.time=self.time+dtime
|
|
if self.time<0.1 then return self end
|
|
self.time=0
|
|
if not (self.ant and self.ant:get_luaentity() and self.ant:get_hp()>0 and self.carry and self.carry:get_attach()) then
|
|
aliveai.punch(self,self.object,20)
|
|
return self
|
|
end
|
|
local c=self.ant:get_pos()
|
|
local pos=self.object:get_pos()
|
|
if not (c and c.x) then aliveai.punch(self,self.object,20) return end
|
|
local v={x=(c.x-pos.x)*4,y=(c.y-pos.y+0.5)*4, z=(c.z-pos.z)*4}
|
|
self.object:set_velocity(v)
|
|
return self
|
|
end,
|
|
time=0,
|
|
type=""
|
|
})
|
|
|