xaenvironment/mods/villages/init.lua

600 lines
17 KiB
Lua

villages = {
default_area = 12,
village_size = {3,5},
buildings = {
["villages_dubble_balcony"]={chance=15,area=10,height=6},
["villages_family_curbroof"]={chance=15,area=12,height=8},
["villages_foodbar"]={chance=15,area=9,height=7},
["villages_litle_house_balcony"]={chance=10,area=5,height=6},
["villages_middle_house"]={chance=12,area=7,height=7},
["villages_storey"]={chance=15,area=8,height=9},
["villages_tiny_curbroof"]={chance=8,area=7,height=5},
["villages_tower"]={chance=15,area=6,height=18},
["villages_cabbage_farm"]={chance=18,area=10,height=2},
["villages_chicken_farm"]={chance=18,area=10,height=3},
["villages_cistern"]={chance=18,area=8,height=2},
["villages_cotton_farm"]={chance=18,area=10,height=2},
["villages_mine_shaft"]={chance=19,area=5,height=1},
["villages_pig_farm"]={chance=18,area=10,height=3},
["villages_sheep_farm"]={chance=18,area=10,height=3},
["villages_wheat_farm"]={chance=18,area=10,height=2},
},
atlantis = {
{name="atlantis_building1",chance=15,area=31,spawn=function(pos)
villages.chests_to_treasures_in_area(pos,16)
end},
{name="atlantis_building2",chance=15,area=17,spawn=function(pos)
villages.chests_to_treasures_in_area(pos,16)
end},
{name="atlantis_building3",chance=15,area=10,spawn=function(pos)
protect.add_game_rule_area(apos(pos,6,14,6),apos(pos,-6,-1,-6),"atlantis")
villages.chests_to_treasures_in_area(pos,17)
end},
{name="atlantis_building4",chance=15,area=13},
{name="atlantis_building5",chance=15,area=16},
{name="atlantis_building6",chance=15,area=36,spawn=function(pos)
protect.add_game_rule_area(vector.subtract(pos,18),vector.add(pos,18),"atlantis")
villages.chests_to_treasures_in_area(pos,18)
local code = math.random(0,9)..math.random(0,9)..math.random(0,9)..math.random(0,9)
local nodes = minetest.find_nodes_in_area(vector.subtract(pos,18),vector.add(pos,18),{"exatec:codelock","materials:granite_orb"})
local I = 0
for i,v in pairs(nodes) do
local n = minetest.get_node(v)
if n.name == "exatec:codelock" then
minetest.set_node(v,{name="exatec:codelock",param2=n.param2})
minetest.get_meta(v):set_string("code",code)
I = i
break
end
end
table.remove(nodes,I)
local p = nodes[math.random(1,#nodes)]
minetest.get_meta(p):set_string("infotext",code)
end},
{name="atlantis_building7",chance=15,area=10},
{name="atlantis_building8",chance=15,area=6},
{name="atlantis_building9",chance=15,area=10,spawn=function(pos)
villages.chests_to_treasures_in_area(pos,16)
end},
{name="atlantis_building10",chance=15,area=32,spawn=function(pos)
protect.add_game_rule_area(vector.subtract(pos,16),vector.add(pos,16),"atlantis")
villages.chests_to_treasures_in_area(pos,16)
end},
},
nodes_reset = {
"default:paper_compressor",
"default:craftguide",
"default:workbench",
"default:recycling_mill",
"default:dye_workbench",
"default:chest",
"examobs:woodbox",
"default:furnace",
"plants:apple_wood_door",
"clock:clock1",
"examobs:villager_npc_spawner",
"examobs:chicken_spawner",
"examobs:sheep_spawner",
"examobs:pig_spawner",
}
}
minetest.register_tool("villages:biocheck", {
description = "Biocheck",
inventory_image = "default_stick.png",
on_use=function(itemstack, user, pointed_thing)
local pos = user:get_pos()
local i = 3
minetest.place_schematic(pos,minetest.get_modpath("villages").."/schematics/atlantis_building"..i..".mts","random",nil,true,"place_center_x,place_center_z")
villages.atlantis[i].spawn(pos)
end
})
villages.chests_to_treasures_in_area=function(pos,rad)
local nodes = minetest.find_nodes_in_area(vector.subtract(pos,rad),vector.add(pos,rad),"default:chest")
for i,v in pairs(nodes) do
default.treasure({level=2,pos=v,node=minetest.get_node(v).name})
end
end
villages.set_village=function(pos)
local s = math.random(villages.village_size[1],villages.village_size[2])
local cs = 0
local used_pos = {}
local node
local nodes1 = minetest.find_nodes_in_area(vector.subtract(pos,20),vector.add(pos,20),{"group:tree"})
if #nodes1 > 0 then
for i,v in pairs(nodes1) do
local tree = minetest.registered_nodes[minetest.get_node(v).name].tree
if tree then
node = tree
break
end
end
else
local nodes2 = minetest.find_nodes_in_area(vector.subtract(pos,10),vector.add(pos,10),{"default:desert_sand"})
if #nodes2 > 0 then
node = "default:desert_cobble"
else
local nodes3 = minetest.find_nodes_in_area(vector.subtract(pos,10),vector.add(pos,10),{"default:dirt_with_grass"})
if #nodes3 > 0 then
node = "default:cobble"
end
end
end
for i = 0,math.random(100,1000) do
if villages.set_building_pos(pos,s,node,used_pos) then
cs = cs + 1
if cs >= (s*s)*s then
break
end
end
end
end
villages.set_atlantis=function(pos)
if pos.y > -25 or minetest.get_node(apos(pos,0,1)).name ~= "default:salt_water_source" then
return
end
pos.y=pos.y+1
local dir = {vector.new(pos),vector.new(pos),vector.new(pos),vector.new(pos)}
local hit = {}
local h = 0
for a=1,200 do
dir[1] = apos(dir[1],1)
dir[2] = apos(dir[2],-1)
dir[3] = apos(dir[3],0,0,1)
dir[4] = apos(dir[4],0,0,-1)
for i=1,4 do
if not hit[i] and minetest.get_node(dir[i]).name ~= "default:salt_water_source" then
hit[i] = vector.new(dir[i])
h = h +1
if h >= 4 then
break
end
end
end
if h >= 4 then
break
end
end
for i=1,4 do
hit[i] = hit[i] or dir[i]
end
local sx = pos.x-hit[1].x + pos.x-hit[2].x
local sz = pos.z-hit[3].z + pos.z-hit[4].z
local npos = {x=pos.x-sx/2,y=pos.y,z=pos.z-sz/2} -- center of area
local sizex,sizez = hit[1].x-hit[2].x,hit[3].z-hit[4].z
if sizez < 50 or sizez < 50 then
return
end
local num = math.random(10,20)
local list = {}
local i = 0
local n = #villages.atlantis
for I=0,100 do
local p = {x=npos.x+math.random(-sizex,sizex),y=npos.y,z=npos.z+math.random(-sizez,sizez)}
local b = villages.atlantis[math.random(1,n)]
local able = true
for i,v in pairs(list) do
local d = vector.distance(v.pos,npos)
if (d-b.area)-v.area <= 0 then
able = false
break
end
end
if able then
table.insert(list,{pos=p,area=b.area})
minetest.place_schematic(p,minetest.get_modpath("villages").."/schematics/"..b.name..".mts","random",nil,true,"place_center_x,place_center_z")
if b.spawn then
b.spawn(p)
end
num = num -1
if num <= 0 then
return
end
end
end
end
villages.set_building_pos=function(pos,size,node,used_pos)
local p = {x=pos.x,y=pos.y,z=pos.z}
local up
for i = 0,10 do
p.x = pos.x + math.random(-size,size)*villages.default_area
p.z = pos.z + math.random(-size,size)*villages.default_area
up = p.x.." "..p.z
if not used_pos[up] then
used_pos[up] = up
local g = villages.find_ground(p)
if g then
if villages.set_building(g,node) then
return true
end
end
end
end
return false
end
villages.find_ground=function(pos)
for i = pos.y-10,pos.y+10 do
local p1 = {x=pos.x,y=i,z=pos.z}
local l1 = minetest.get_node_light(p1,0.5)
local p2 = {x=pos.x,y=i+1,z=pos.z}
local l2 = minetest.get_node_light(p2,0.5)
if l1 == nil then
minetest.emerge_area(p1,p2)
l1 = minetest.get_node_light(p1,0.5)
l2 = minetest.get_node_light(p2,0.5)
end
if i > 0 and (l2 or 0) > 9 and (l1 or 0) == 0 then
return p1
end
end
end
villages.set_building=function(pos,node)
local s
local name
minetest.emerge_area(vector.subtract(pos,-villages.default_area),vector.add(pos,villages.default_area))
local ground = minetest.get_node(pos)
for i,v in pairs(villages.buildings) do
if math.random(1,v.chance) == 1 then
local a = minetest.find_nodes_in_area(vector.subtract(pos,v.area/2),vector.add(pos,v.area/2),{"group:stone","group:dirt"})
local c = #a
local bc = ((v.area*v.area) * v.area)/2 + (v.area*v.area)*2
if c <= bc and c >bc/1.5 then
minetest.place_schematic(pos,minetest.get_modpath("villages").."/schematics/"..i..".mts","random",nil,true,"place_center_x,place_center_z")
name = i
break
end
end
end
if not name then
return false
end
local prop = villages.buildings[name]
local a = math.ceil(prop.area/2)
local h = prop.height
local nodes = minetest.find_nodes_in_area({x=pos.x+a,y=pos.y,z=pos.z+a},{x=pos.x-a,y=pos.y+h,z=pos.z-a},villages.nodes_reset)
for i,v in pairs(nodes) do
local n = minetest.get_node(v)
if n.name == "examobs:villager_npc_spawner" then
minetest.remove_node(v)
local self = minetest.add_entity(v,"examobs:villager_npc"):get_luaentity()
self.storage.npc_generated = true
self.storage.property_area = prop.area
self.storage.property_area_pos = pos
elseif n.name == "examobs:chicken_spawner" then
minetest.remove_node(v)
minetest.add_entity(v,"examobs:chicken"):set_yaw(math.random(0,6.28))
elseif n.name == "examobs:sheep_spawner" then
minetest.remove_node(v)
minetest.add_entity(v,"examobs:sheep"):set_yaw(math.random(0,6.28))
elseif n.name == "examobs:pig_spawner" then
minetest.remove_node(v)
minetest.add_entity(v,"examobs:pig"):set_yaw(math.random(0,6.28))
elseif n.name == "default:chest" or n.name == "examobs:woodbox" then
default.treasure({pos=v,node=n})
else
minetest.set_node(v,n)
end
end
for x = -a,a do
for z = -a,a do
local p = {x=pos.x+x,y=pos.y,z=pos.z+z}
local p2 = {x=pos.x+x,y=pos.y-1,z=pos.z+z}
if minetest.get_node(p).name == "air" and minetest.get_node(p2).name ~= "air" then
minetest.set_node(p,ground)
end
end
end
if not node then
return true
end
local nodes = minetest.find_nodes_in_area({x=pos.x-a,y=pos.y,z=pos.z-a},{x=pos.x+a,y=pos.y+h,z=pos.z+a},{"group:chair","group:door","group:wood","group:tree","group:fence"})
if string.find(node,":") then
for i,v in pairs(nodes) do
local n = minetest.get_node(v)
local na = n.name
if minetest.get_item_group(na,"wood") > 0 or minetest.get_item_group(na,"tree") > 0 then
minetest.set_node(v,{name=node})
else
minetest.remove_node(v)
end
end
else
for i,v in pairs(nodes) do
local n = minetest.get_node(v)
local na = string.gsub(n.name,"apple",node)
minetest.set_node(v,{name=na,param2=n.param2})
end
end
return true
end
minetest.register_node("villages:spawner", {
drawtype = "airlike",
paramtype = "light",
walkable = false,
buildable_to = true,
groups={on_load=1,not_in_creative_inventory=1},
on_load=function(pos)
minetest.remove_node(pos)
local n = minetest.get_node({x=pos.x+math.random(-1,1),y=pos.y,z=pos.z+math.random(-1,1)})
minetest.set_node(pos,n)
if math.random(1,10) == 1 then
villages.set_village(pos)
end
end,
})
minetest.register_node("villages:atlantis_spawner", {
drawtype = "airlike",
paramtype = "light",
walkable = false,
buildable_to = true,
groups={on_load=1,not_in_creative_inventory=1},
on_load=function(pos)
minetest.remove_node(pos)
local n = minetest.get_node({x=pos.x+math.random(-1,1),y=pos.y,z=pos.z+math.random(-1,1)})
minetest.set_node(pos,n)
if math.random(1,10) == 1 then
villages.set_atlantis(pos)
end
end,
})
minetest.register_ore({
ore_type = "blob",
ore= "villages:atlantis_spawner",
wherein= "default:sand",
clust_scarcity = 30 * 30 * 30,
clust_size = 1,
y_min= -200,
y_max= -25,
noise_params = default.ore_noise_params()
})
minetest.register_ore({
ore_type = "blob",
ore= "villages:spawner",
wherein= "default:dirt",
clust_scarcity = 30 * 30 * 30,
clust_size = 1,
y_min= 0,
y_max= 50,
noise_params = default.ore_noise_params()
})
minetest.register_ore({
ore_type = "blob",
ore= "villages:spawner",
wherein= "default:snow",
clust_scarcity = 30 * 30 * 30,
clust_size = 1,
y_min= 0,
y_max= 50,
noise_params = default.ore_noise_params()
})
minetest.register_ore({
ore_type = "blob",
ore= "villages:spawner",
wherein= "default:desert_sand",
clust_scarcity = 30 * 30 * 30,
clust_size = 1,
y_min= 0,
y_max= 50,
noise_params = default.ore_noise_params()
})
minetest.register_node("villages:trader", {
groups = {attached_node=1,not_in_creative_inventory=1,on_load=1},
pointable=false,
paramtype = "light",
drawtype="airlike",
drop="",
walkable=false,
floodable = true,
sunlight_propagates = true,
on_construct=function(pos)
minetest.get_node_timer(pos):start(3)
end,
on_timer = function (pos, elapsed)
local npc
local item
for _, ob in ipairs(minetest.get_objects_inside_radius(pos,10)) do
local en = ob:get_luaentity()
if en and en.examob and en.type == "npc" then
npc = true
elseif en and en.traderitem and vector.distance(ob:get_pos(),pos) <= 0.3 then
item = ob
end
if npc and item then
break
end
end
if minetest.get_meta(pos):get_string("item1") == "" then
minetest.registered_nodes["villages:trader"].newitem(pos)
end
if not npc then
if item then
item:remove()
end
elseif not item then
minetest.registered_nodes["villages:trader"].spawnitem(pos)
end
return true
end,
on_load=function(pos)
if math.random(1,5) == 1 or minetest.get_meta(pos):get_string("item1") == "" then
minetest.get_node_timer(pos):start(3)
minetest.registered_nodes["villages:trader"].newitem(pos)
minetest.registered_nodes["villages:trader"].spawnitem(pos)
for _, ob in ipairs(minetest.get_objects_inside_radius(pos,0.3)) do
local en = ob:get_luaentity()
if en and en.traderitem then
ob:remove()
end
end
end
end,
spawnitem=function(pos)
local e = minetest.add_entity(pos,"villages:traderitem"):get_luaentity()
e.index = minetest.get_meta(pos):get_int("index")
e:on_rightclick()
end,
newitem=function(pos)
local items = {}
local m = minetest.get_meta(pos)
for i,v in pairs(minetest.registered_items) do
if minetest.get_item_group(i,"store") > 1 then
table.insert(items,i)
end
end
for i=1,10 do
local item = items[math.random(1,#items)]
local cost = minetest.get_item_group(item,"store")
m:set_string("item"..i,item)
m:set_int("index",1)
m:set_int("count"..i,math.random(1,10))
m:set_int("cost"..i,cost+math.floor(math.random(cost*0.1,cost*2)))
end
end,
})
local trader2 = table.copy(default.def("villages:trader"))
trader2.on_timer = function(pos, elapsed)
local item
for _, ob in ipairs(minetest.get_objects_inside_radius(pos,10)) do
local en = ob:get_luaentity()
if en and en.traderitem and vector.distance(ob:get_pos(),pos) <= 0.3 then
item = ob
break
end
end
if minetest.get_meta(pos):get_string("item1") == "" then
minetest.registered_nodes["villages:trader"].newitem(pos)
end
if not item then
minetest.registered_nodes["villages:trader"].spawnitem(pos)
end
return true
end
minetest.register_node("villages:trader2", trader2)
minetest.register_entity("villages:traderitem",{
hp_max = 1000,
physical = false,
collisionbox = {-0.3,-0.3,-0.3,0.3,0.3,0.3},
visual = "wielditem",
visual_size = {x=0.3,y=0.3},
textures = {"default:stick"},
decoration=true,
traderitem=true,
static_save = false,
automatic_rotate = math.pi/4,
timer = 0,
on_step=function(self, dtime)
self.timer = self.timer -dtime
if self.timer < 0 then
self.timer = 1
local n = minetest.get_node(self.object:get_pos()).name
if n ~= "villages:trader" and n ~= "villages:trader2" then
self.object:remove()
end
end
end,
on_punch=function(self, puncher, time_from_last_punch, tool_capabilities, dir)
self.object:set_hp(1000)
if puncher:is_player() then
local inv = puncher:get_inventory()
local c = Getcoin(puncher)
local pos = self.object:get_pos()
local m2 = minetest.get_meta(pos)
if c >= self.cost and inv:room_for_item("main",self.item) then
inv:add_item("main",self.item)
Coin(puncher,c-self.cost,true)
local ic = m2:get_int("count"..self.index)-1
m2:set_int("count"..self.index,ic)
self.update = true
self.on_rightclick(self)
end
end
end,
on_rightclick=function(self)
local pos = self.object:get_pos()
local items = {}
local m = minetest.get_meta(pos)
local set
if self.update == nil or m:get_int("count"..self.index) <= 0 then
for i = self.index+1,10 do
if m:get_int("count"..i) > 0 then
self.index = i
set = true
break
end
end
if not set then
for i = 1,self.index do
if m:get_int("count"..i) > 0 then
self.index = i
set = true
break
end
end
if not set then
minetest.registered_nodes["villages:trader"].newitem(pos)
minetest.registered_nodes["villages:trader"].spawnitem(pos)
self.object:remove()
return
end
end
m:set_int("index",self.index)
end
self.update = nil
self.item = m:get_string("item"..self.index)
self.cost = m:get_int("cost"..self.index)
local def = minetest.registered_items[self.item]
if not def then
minetest.registered_nodes["villages:trader"].newitem(pos)
minetest.registered_nodes["villages:trader"].spawnitem(pos)
self.object:remove()
return
end
self.object:set_properties(
{textures={self.item},
infotext=(def.description or def.name) .. "\nCost: "..self.cost.."\n"..m:get_int("count"..self.index).." left\n"..self.index.."/10\n\nRight click to change"
})
end,
})