Beta Release.

This commit is contained in:
secXsQuared 2018-01-27 19:44:49 -05:00
parent 4f11d8b07e
commit 5959c9e84a
6 changed files with 265 additions and 121 deletions

Binary file not shown.

View File

@ -1,3 +0,0 @@
<Atlas><Texture filename="modicon.tex" />
<Elements><Element name="modicon.tex" u1="0" u2="1" v1="0" v2="1" />
</Elements></Atlas>

View File

@ -1,15 +1,103 @@
name = "Advanced World Regrowth"
description = "Advanced world regrowth"
description = "Advanced world regrowth including caves!\nSee the Steam Workshop page for more information."
author = "lolo"
version = "1.0.0"
version = "0.1.0"
forumthread = ""
api_version = 10
icon_atlas = "modicon.xml"
icon = "modicon.tex"
--icon_atlas = "modicon.xml"
--icon = "modicon.tex"
all_clients_require_mod = false
client_only_mod = false
dst_compatible = true
dst_compatible = true
-- Configuration Generation
local config_table =
{
{"evergreen","Evergreen","Natural"},
{"deciduoustree","Birchnut Tree","Natural"},
{"marsh_tree","Spiky Tree","Natural"},
{"twiggytree","Twiggy Tree","Natural"},
{"marbletree","Marble Tree","Event-based"},
{"livingtree","Totally Normal Tree","Event-based"},
{"berrybush","Berry Bush","Natural"},
{"berrybush2","Spiky Berry Bush","Natural"},
{"berrybush_juicy","Juicy Berry Bush","Natural"},
{"carrot_planted","Carrot","Natural"},
{"flower","Flower","Natural"},
{"flower_evil","Evil Flower","Event-based"},
{"blue_mushroom","Blue Mushroom","Natural"},
{"red_mushroom","Red Mushroom","Natural"},
{"green_mushroom","Green Mushroom","Natural"},
{"cactus","Cactus","Natural"},
{"mandrake","Mandrake","Event-based"},
{"reeds","Reeds","Natural"},
{"sapling","Sapling","Natural"},
{"grass","Grass","Natural"},
{"marsh_bush","Spiky Bush","Natural"},
{"rock1","Boulder","Natural"},
{"rock2","Gold Vein","Natural"},
{"rock_flintless","Flintless Boulder","Natural"},
{"rock_moon","Moon Rock","Natural"},
{"stalagmite","Stalagmite","Natural"},
{"stalagmite_tall","Tall Stalagmite","Natural"},
{"beehive","Beehive","Event-based"},
{"wasphive","Killer Bee Hive","Event-based"},
{"houndmound","Hound Mound","Event-based"},
{"pighouse","Pig House","Event-based"},
{"mermhouse","Rundown House","Event-based"},
{"spiderden","Spider Den","Event-based"},
{"catcoonden","Hollow Stump","Event-based"},
{"rabbithouse","Rabbit Hutch","Event-based"},
{"monkeypods","Splumonkey Pod","Event-based"},
{"slurtlehole", "Slurtle Mound", "Event-based"},
{"fireflies","Fireflies","Event-based"},
{"tentacle","Tentacle","Event-based"},
{"knight","Clockwork Knight","Event-based"},
{"bishop","Clockwork Bishop","Event-based"},
{"rook","Clockwork Rook","Event-based"},
{"knight_nightmare","Damaged Knight","Event-based"},
{"bishop_nightmare","Damaged Bishop","Event-based"},
{"rook_nightmare","Damaged Rook","Event-based"},
{"ruins_statue_mage","Ancient Mage Statue","Event-based"},
{"ruins_statue_mage_nogem","Gemless Ancient Mage Statue","Event-based"},
{"ruins_statue_head","Ancient Head Statue","Event-based"},
{"ruins_statue_head_nogem", "Gemless Ancient Head Statue", "Event-based"}
}
local config_options = {}
for i = 1, #config_table do
local entry =
{
name = config_table[i][1],
label = config_table[i][2],
hover = config_table[i][3],
options =
{
{
description = "Disabled",
data = false
},
{
description = "Enabled",
data = true
}
},
default = true
}
config_options[#config_options+1] = entry
end
configuration_options = config_options

View File

@ -24,75 +24,76 @@ end
local natural =
{
--plants
berrybush = 1440,
berrybush2 = 1440,
berrybush_juicy = 1440,
berrybush = 1451,
berrybush2 = 1429,
berrybush_juicy = 1429,
carrot_planted = 240,
evergreen = 30,
deciduoustree = 30,
evergreen = 251,
deciduoustree = 251,
marsh_tree = 480,
twiggytree = 480,
flower = 240,
flower_evil = 480,
grass = 240,
blue_mushroom = 240,
twiggytree = 491,
flower = 229,
grass = 229,
blue_mushroom = 251,
red_mushroom = 240,
green_mushroom = 240,
reeds = 480,
sapling = 240,
marsh_bush = 480,
cactus = 480,
rock1 = 240,
cactus = 479,
rock1 = 229,
rock2 = 240,
rock_flintless = 240,
marbletree=1440,
rock_flintless = 251,
rock_moon = 480,
stalagmite = 240,
stalagmite = 489,
stalagmite_tall = 240,
}
local event =
{
houndbone = 960,
pighead = 960,
marblepillar = 1440,
livingtree = 960,
mandrake = 960,
beehive = 480,
wasphive = 960,
houndmound = 1440,
flower_evil = 480,
marbletree= 960,
livingtree = 969,
mandrake = 969,
beehive = 489,
wasphive = 969,
houndmound = 1449,
pighouse = 960,
mermhouse = 960,
spiderden = 960,
molehill = 960,
catcoonden = 960,
tentacle = 480,
rabbithole = 480,
fireflies = 480,
knight = 23,
bishop = 9,
rook = 34,
knight_nightmare = 1440,
spiderden = 1431,
catcoonden = 951,
tentacle = 489,
rabbithole = 471,
fireflies = 471,
knight = 1431,
bishop = 1431,
rook = 1449,
knight_nightmare = 1449,
bishop_nightmare = 1440,
rook_nightmare = 1440,
monkeypods = 1440,
ruins_statue_mage = 960,
ruins_statue_mage_nogem = 960,
monkeypods = 951,
ruins_statue_mage = 969,
ruins_statue_mage_nogem = 969,
ruins_statue_head = 960,
ruins_statue_head_nogem = 960,
rabbithouse = 960
ruins_statue_head_nogem = 951,
rabbithouse = 951,
slurtlehole = 951
}
AddComponentPostInit("natural_regrowth", function(component)
for prefab, time in pairs(natural) do
component:RegisterRegrowth(prefab, prefab, time)
if GetModConfigData(prefab) then
component:RegisterRegrowth(prefab, prefab, time)
end
end
component:FinishModConfig()
end)
AddComponentPostInit("event_regrowth", function(component)
for prefab, time in pairs(event) do
component:RegisterRegrowth(prefab, prefab, time)
if GetModConfigData(prefab) then
component:RegisterRegrowth(prefab, prefab, time)
end
end
component:FinishModConfig()
end)

View File

@ -15,17 +15,17 @@ return Class(function(self, inst)
--------------------------------------------------------------------------
--[[ Constants ]]
--------------------------------------------------------------------------
local DEBUG = true
local DEBUG = false
local DEBUG_TELE = false
local UPDATE_PERIOD = 11
local UPDATE_PERIOD = 9
local BASE_RADIUS = 20
local EXCLUDE_RADIUS = 3
local JITTER_RADIUS = 6
local TOTAL_RADIUS = 1000
local MIN_PLAYER_DISTANCE = 40
local THREADS_PER_BATCH = 5 -- since we retry a lot, we reduce the # of threads to guarantee performance
local THREADS_PER_BATCH_HOOK = 5
local THREADS_PER_BATCH = 3
local THREADS_PER_BATCH_HOOK = 2
local REGROW_STATUS = {
SUCCESS = 0,
FAILED = 1,
@ -54,7 +54,7 @@ return Class(function(self, inst)
end
local position = ent:GetPosition()
table.insert(entity_list[ent.prefab], {position = position, interval = regrowth_table[ent.prefab].interval})
entity_list[ent.prefab][#entity_list[ent.prefab]+1] = {position = position, interval = regrowth_table[ent.prefab].interval}
ent:RemoveEventCallback("onremove", EntityDeathEventHandler, nil)
if DEBUG then
@ -63,24 +63,25 @@ return Class(function(self, inst)
end
local function TestForRegrow(x, y, z, tile)
if IsAnyPlayerInRange(x,y,z, MIN_PLAYER_DISTANCE, nil) then
return REGROW_STATUS.CACHE
end
local ents = TheSim:FindEntities(x,y,z, BASE_RADIUS, nil, nil, { "structure", "wall" })
if #ents > 0 then
if #ents > 0 then
-- No regrowth around players and their bases
return REGROW_STATUS.FAILED
end
if inst.Map:GetTileAtPoint(x, y, z) ~= tile then
-- keep things in their biome (more or less)
return REGROW_STATUS.CACHE
end
local ents = TheSim:FindEntities(x,y,z, EXCLUDE_RADIUS)
if #ents > 0 then
-- Too dense
return REGROW_STATUS.CACHE
end
if IsAnyPlayerInRange(x,y,z, MIN_PLAYER_DISTANCE, nil) then
if inst.Map:GetTileAtPoint(x, y, z) ~= tile then
-- keep things in their biome (more or less)
return REGROW_STATUS.CACHE
end
@ -211,6 +212,7 @@ return Class(function(self, inst)
product = product,
interval = interval
}
HookEntities(prefab)
end
@ -230,9 +232,9 @@ return Class(function(self, inst)
--------------------------------------------------------------------------
--[[ Update ]]
--------------------------------------------------------------------------
local function RegrowPrefabTask(prefab)
local function RegrowPrefabTask(prefab, position)
for i = #entity_list[prefab],1,-1 do
local success = TryRegrowth(prefab, regrowth_table[prefab].product, entity_list[prefab][i].position)
local success = TryRegrowth(prefab, regrowth_table[prefab].product, position)
if success then
-- remove from the list if it's success or failed
@ -273,7 +275,7 @@ return Class(function(self, inst)
if entity_list[prefab][i].interval == 0 then
-- different threads
inst:DoTaskInTime(delay, function() RegrowPrefabTask(prefab) end)
inst:DoTaskInTime(delay, function() RegrowPrefabTask(prefab, entity_list[prefab][i].position) end)
-- try not to flood the server with threads
count = count + 1
@ -296,9 +298,15 @@ return Class(function(self, inst)
entities = {}
}
for prefab in pairs(entity_list) do
data.entities[prefab] = {}
for i = 1, #entity_list[prefab] do
table.insert(data.entities[prefab], {interval = entity_list[prefab][i].interval, position = entity_list[prefab][i].position})
if entity_list[prefab] ~= nil then
-- could be nil (set in the event loop)
data.entities[prefab] = {}
for i = 1, #entity_list[prefab] do
data.entities[prefab][#data.entities[prefab] + 1] = {interval = entity_list[prefab][i].interval, position = entity_list[prefab][i].position}
end
if DEBUG then
print("[EventRegrowth] Saved ", #data.entities[prefab]," entities for ", prefab)
end
end
end
return data
@ -308,9 +316,12 @@ return Class(function(self, inst)
for prefab in pairs(data.entities) do
if entity_list[prefab] == nil then
entity_list[prefab] = {}
end
for i = 1, #data.entities[prefab] do
table.insert(entity_list[prefab], {interval = data.entities[prefab][i].interval, position = data.entities[prefab][i].position})
for i = 1, #data.entities[prefab] do
entity_list[prefab][#entity_list[prefab] + 1] = {interval = data.entities[prefab][i].interval, position = data.entities[prefab][i].position}
end
if DEBUG then
print("[EventRegrowth] Loaded ", #entity_list[prefab]," entities for ", prefab)
end
end
end
end

View File

@ -8,7 +8,7 @@
return Class(function(self, inst)
assert(inst.ismastersim, "natrual_regrowth should not exist on client")
assert(inst.ismastersim, "natural_regrowth should not exist on client")
require "map/terrain"
@ -17,11 +17,11 @@ return Class(function(self, inst)
--------------------------------------------------------------------------
local DEBUG = false
local DEBUG_TELE = false
local UPDATE_PERIOD = 9
local UPDATE_PERIOD = 11
local BASE_RADIUS = 20
local EXCLUDE_RADIUS = 3
local MIN_PLAYER_DISTANCE = 40
local THREADS_PER_BATCH = 5
local THREADS_PER_BATCH = 3
--------------------------------------------------------------------------
--[[ Member variables ]]
--------------------------------------------------------------------------
@ -33,6 +33,7 @@ return Class(function(self, inst)
local regrowth_table = {}
local area_data = {}
local intervals = {}
local regrowth_table_populated_by_mod = false
--------------------------------------------------------------------------
--[[ Private member functions ]]
@ -65,18 +66,7 @@ return Class(function(self, inst)
return true
end
local function TryRegrowth(area, prefab, product)
if inst.topology.nodes[area] == nil then
return false
end
local points_x, points_y = inst.Map:GetRandomPointsForSite(inst.topology.nodes[area].x, inst.topology.nodes[area].y, inst.topology.nodes[area].poly, 1)
if #points_x < 1 or #points_y < 1 then
return false
end
local x = points_x[1]
local z = points_y[1]
local function TryRegrowth(x, y, z , prefab, product)
if CanRegrow(x,0,z, product) then
local instance = SpawnPrefab(product)
@ -85,7 +75,7 @@ return Class(function(self, inst)
end
if DEBUG then
print("[NaturalRegrowth] Spawned a ",product," for prefab ",prefab," at ", "(", x,0,z, ")", " in ", area)
print("[NaturalRegrowth] Spawned a ",product," for prefab ",prefab," at ", "(", x,0,z, ")")
end
if DEBUG_TELE then
@ -95,7 +85,7 @@ return Class(function(self, inst)
return true
else
if DEBUG then
print("[NaturalRegrowth] Failed to spawn a ",product," for prefab ",prefab," at ", "(", x,0,z, ")", " in ", area)
print("[NaturalRegrowth] Failed to spawn a ",product," for prefab ",prefab," at ", "(", x,0,z, ")")
end
return false
end
@ -111,12 +101,18 @@ return Class(function(self, inst)
local function PopulateAreaData(prefab)
if inst.generated == nil then
-- Still starting up, not ready yet.
-- Still starting up
return
end
if area_data[prefab] ~= nil then
if DEBUG then
print("[NaturalRegrowth] Already populated ", prefab)
end
return
end
-- PrintDensities()
for area, densities in pairs(inst.generated.densities) do
if densities[prefab] ~= nil then
for id, v in ipairs(inst.topology.ids) do
@ -125,7 +121,7 @@ return Class(function(self, inst)
area_data[prefab] = {}
end
table.insert(area_data[prefab], id)
area_data[prefab][#area_data[prefab] + 1] = id
break
end
end
@ -147,6 +143,10 @@ return Class(function(self, inst)
--------------------------------------------------------------------------
--[[ Public member functions ]]
--------------------------------------------------------------------------
function self:FinishModConfig()
regrowth_table_populated_by_mod = true
end
function self:RegisterRegrowth(prefab, product, interval)
if DEBUG then
@ -173,9 +173,32 @@ return Class(function(self, inst)
--[[ Update ]]
--------------------------------------------------------------------------
-- duplicate of event_regrowth
local function GetRandomLocation(x, y, z, radius)
local theta = math.random() * 2 * PI
local radius = math.random() * radius
local x = x + radius * math.cos(theta)
local z = z - radius * math.sin(theta)
return x,y,z
end
local function RegrowPrefabTask(areas, prefab)
local success = false
local rand = math.random(1, #areas)
local success = TryRegrowth(areas[rand], prefab, regrowth_table[prefab].product)
local area = areas[rand]
if inst.topology.nodes[area] == nil then
return false
end
local points_x, points_y = inst.Map:GetRandomPointsForSite(inst.topology.nodes[area].x, inst.topology.nodes[area].y, inst.topology.nodes[area].poly, 1)
if #points_x < 1 or #points_y < 1 then
return false
end
success = TryRegrowth(points_x[1], 0, points_y[1], prefab, regrowth_table[prefab].product)
if success then
-- success, reset the timer
intervals[prefab] = regrowth_table[prefab] == nil and nil or regrowth_table[prefab].interval
@ -183,35 +206,42 @@ return Class(function(self, inst)
end
function self:LongUpdate(dt)
if not regrowth_table_populated_by_mod then
-- do nothing if the table is not fully initialized
-- in case we accidentally drop some saved entities due to the respawn_table[prefab] == nil check
return
end
local count = 0
local delay = 0
-- area data because we only care about stuff that can naturally spawn
for prefab in pairs(area_data) do
local areas = area_data[prefab]
if regrowth_table[prefab] == nil then
area_data[prefab] = nil
intervals[prefab] = nil
else
if intervals[prefab] > UPDATE_PERIOD then
intervals[prefab] = intervals[prefab] - UPDATE_PERIOD
if regrowth_table[prefab] == nil or area_data[prefab] == nil then
-- if regrowth table didn't register, or the entity doesn't have a natural density, do nothing
intervals[prefab] = nil
else
intervals[prefab] = 0
end
if DEBUG then
print("[NaturalRegrowth]", prefab, " has interval ", intervals[prefab])
end
if intervals[prefab] > UPDATE_PERIOD then
intervals[prefab] = intervals[prefab] - UPDATE_PERIOD
else
intervals[prefab] = 0
end
if DEBUG then
print("[NaturalRegrowth]", prefab, " has interval ", intervals[prefab])
end
if intervals[prefab] == 0 then
-- use multiple threads? In the future a threadpool maybe?
inst:DoTaskInTime(delay, function() RegrowPrefabTask(areas,prefab) end)
-- try not to flood the server with threads
count = count + 1
if math.fmod( count,THREADS_PER_BATCH ) == 0 then
delay = delay + 1
if intervals[prefab] == 0 then
-- use multiple threads? In the future a threadpool maybe?
inst:DoTaskInTime(delay, function() RegrowPrefabTask(area_data[prefab], prefab) end)
-- try not to flood the server with threads
count = count + 1
if math.fmod( count,THREADS_PER_BATCH ) == 0 then
delay = delay + 1
end
end
end
end
end
end
@ -228,27 +258,44 @@ return Class(function(self, inst)
data.areas[prefab] = {}
for i = 1, #area_data[prefab] do
table.insert(data.areas[prefab], area_data[prefab][i])
data.areas[prefab][#data.areas[prefab] + 1] = area_data[prefab][i]
end
if DEBUG then
print("[NaturalRegrowth] Saved ", #data.areas[prefab]," areas for ", prefab)
end
end
for prefab, interval in pairs(intervals) do
data.intervals[prefab] = interval
if interval ~= nil then
-- it can be set to nil in the event loop
data.intervals[prefab] = interval
if DEBUG then
print("[NaturalRegrowth] Saved interval ", data.intervals[prefab]," for ", prefab)
end
end
end
return data
end
function self:OnLoad(data)
for prefab in pairs(data.areas) do
if area_data[prefab] == nil then
area_data[prefab] = {}
end
for i = 1, #data.areas[prefab] do
table.insert(area_data[prefab], data.areas[prefab][i])
if area_data[prefab] == nil then
area_data[prefab] = {}
for i = 1, #data.areas[prefab] do
area_data[prefab][#area_data[prefab] + 1] = data.areas[prefab][i]
end
if DEBUG then
print("[NaturalRegrowth] Loaded", #area_data[prefab]," areas for ", prefab)
end
end
end
for prefab, interval in pairs(data.intervals) do
intervals[prefab] = interval
if DEBUG then
print("[NaturalRegrowth] Loaded interval ", intervals[prefab]," for ", prefab)
end
end
end