Ver 2.0 with ocean support
This commit is contained in:
parent
4812518e76
commit
4e4cf915cd
@ -1,6 +1,6 @@
|
|||||||
name = "World Regrowth++"
|
name = "World Regrowth++"
|
||||||
version = "1.0"
|
version = "2.0"
|
||||||
description = "Version "..version.."\n\nWorld regrowth with caves support. Please see the Steam Workshop page for changes notes.\n\nHappy hunting and do starve!"
|
description = "Version "..version.."\n\nWorld regrowth with caves and ocean support. Please see the Steam Workshop page for changes notes.\n\nHappy hunting and do starve!"
|
||||||
author = "lolo"
|
author = "lolo"
|
||||||
|
|
||||||
forumthread = ""
|
forumthread = ""
|
||||||
@ -16,54 +16,53 @@ dst_compatible = true
|
|||||||
|
|
||||||
local REGROWTH_TYPE =
|
local REGROWTH_TYPE =
|
||||||
{
|
{
|
||||||
NATURAL = 1,
|
EVENT = 1
|
||||||
EVENT = 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Configuration Generation
|
-- Configuration Generation
|
||||||
-- I can't reference this from another file... duplicate
|
-- I can't reference this from another file... duplicate
|
||||||
local config_table =
|
local config_table =
|
||||||
{
|
{
|
||||||
{"evergreen","Evergreen", REGROWTH_TYPE.NATURAL, 1},
|
{"evergreen","Evergreen", REGROWTH_TYPE.EVENT, 1},
|
||||||
{"deciduoustree","Birchnut Tree",REGROWTH_TYPE.NATURAL, 1},
|
{"deciduoustree","Birchnut Tree",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"marsh_tree","Spiky Tree",REGROWTH_TYPE.NATURAL, 2},
|
{"marsh_tree","Spiky Tree",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"twiggytree","Twiggy Tree",REGROWTH_TYPE.NATURAL, 2},
|
{"twiggytree","Twiggy Tree",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"marbletree","Marble Tree",REGROWTH_TYPE.EVENT, 4},
|
{"marbletree","Marble Tree",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"livingtree","Totally Normal Tree",REGROWTH_TYPE.EVENT, 4},
|
{"livingtree","Totally Normal Tree",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.NATURAL, 1},
|
{"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.EVENT, 1},
|
||||||
{"mushtree_medium","Red Mushtree",REGROWTH_TYPE.NATURAL, 1},
|
{"mushtree_medium","Red Mushtree",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"mushtree_small","Green Mushtree", REGROWTH_TYPE.NATURAL, 1},
|
{"mushtree_small","Green Mushtree", REGROWTH_TYPE.EVENT, 1},
|
||||||
|
|
||||||
{"berrybush","Berry Bush",REGROWTH_TYPE.NATURAL, 4},
|
{"berrybush","Berry Bush",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.NATURAL, 4},
|
{"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.NATURAL, 4},
|
{"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.EVENT, 4},
|
||||||
|
|
||||||
{"carrot_planted","Carrot",REGROWTH_TYPE.NATURAL, 1},
|
{"carrot_planted","Carrot",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower","Flower",REGROWTH_TYPE.NATURAL, 1},
|
{"flower","Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_evil","Evil Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_evil","Evil Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_cave","Light Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_cave","Light Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_cave_double","Double Light Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_cave_double","Double Light Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_cave_triple","Triple Light Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_cave_triple","Triple Light Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.NATURAL, 1},
|
{"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"red_mushroom","Red Mushroom",REGROWTH_TYPE.NATURAL, 1},
|
{"red_mushroom","Red Mushroom",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"green_mushroom","Green Mushroom",REGROWTH_TYPE.NATURAL, 1},
|
{"green_mushroom","Green Mushroom",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"cactus","Cactus",REGROWTH_TYPE.NATURAL, 2},
|
{"cactus","Cactus",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"mandrake_planted","Mandrake",REGROWTH_TYPE.EVENT, 6},
|
{"mandrake_planted","Mandrake",REGROWTH_TYPE.EVENT, 6},
|
||||||
{"cave_fern","Fern",REGROWTH_TYPE.NATURAL, 1},
|
{"cave_fern","Fern",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"lichen","Lichen",REGROWTH_TYPE.NATURAL, 1},
|
{"lichen","Lichen",REGROWTH_TYPE.EVENT, 1},
|
||||||
|
|
||||||
{"reeds","Reeds",REGROWTH_TYPE.NATURAL, 2},
|
{"reeds","Reeds",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"sapling","Sapling",REGROWTH_TYPE.NATURAL, 1},
|
{"sapling","Sapling",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"grass","Grass",REGROWTH_TYPE.NATURAL, 1},
|
{"grass","Grass",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"marsh_bush","Spiky Bush",REGROWTH_TYPE.NATURAL, 2},
|
{"marsh_bush","Spiky Bush",REGROWTH_TYPE.EVENT, 2},
|
||||||
|
|
||||||
{"rock1","Boulder",REGROWTH_TYPE.NATURAL, 1},
|
{"rock1","Boulder",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"rock2","Gold Vein",REGROWTH_TYPE.NATURAL, 1},
|
{"rock2","Gold Vein",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"rock_flintless","Flintless Boulder",REGROWTH_TYPE.NATURAL, 2},
|
{"rock_flintless","Flintless Boulder",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"rock_moon","Moon Rock",REGROWTH_TYPE.NATURAL, 2},
|
{"rock_moon","Moon Rock",REGROWTH_TYPE.EVENT, 2},
|
||||||
|
|
||||||
{"stalagmite","Stalagmite",REGROWTH_TYPE.NATURAL, 1},
|
{"stalagmite","Stalagmite",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.NATURAL, 1},
|
{"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.EVENT, 1},
|
||||||
|
|
||||||
{"rabbithole","Rabbit Hole",REGROWTH_TYPE.EVENT, 2},
|
{"rabbithole","Rabbit Hole",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"beehive","Beehive",REGROWTH_TYPE.EVENT, 4},
|
{"beehive","Beehive",REGROWTH_TYPE.EVENT, 4},
|
||||||
|
@ -1,55 +1,52 @@
|
|||||||
local REGROWTH_TYPE =
|
local REGROWTH_TYPE =
|
||||||
{
|
{
|
||||||
NATURAL = 1,
|
EVENT = 1
|
||||||
EVENT = 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
local DEBUG = false
|
|
||||||
|
|
||||||
-- Configuration Generation
|
-- Configuration Generation
|
||||||
-- I can't reference this from another file... duplicate
|
-- I can't reference this from another file... duplicate
|
||||||
local config_table =
|
local config_table =
|
||||||
{
|
{
|
||||||
{"evergreen","Evergreen", REGROWTH_TYPE.NATURAL, 1},
|
{"evergreen","Evergreen", REGROWTH_TYPE.EVENT, 1},
|
||||||
{"deciduoustree","Birchnut Tree",REGROWTH_TYPE.NATURAL, 1},
|
{"deciduoustree","Birchnut Tree",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"marsh_tree","Spiky Tree",REGROWTH_TYPE.NATURAL, 2},
|
{"marsh_tree","Spiky Tree",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"twiggytree","Twiggy Tree",REGROWTH_TYPE.NATURAL, 2},
|
{"twiggytree","Twiggy Tree",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"marbletree","Marble Tree",REGROWTH_TYPE.EVENT, 4},
|
{"marbletree","Marble Tree",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"livingtree","Totally Normal Tree",REGROWTH_TYPE.EVENT, 4},
|
{"livingtree","Totally Normal Tree",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.NATURAL, 1},
|
{"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.EVENT, 1},
|
||||||
{"mushtree_medium","Red Mushtree",REGROWTH_TYPE.NATURAL, 1},
|
{"mushtree_medium","Red Mushtree",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"mushtree_small","Green Mushtree", REGROWTH_TYPE.NATURAL, 1},
|
{"mushtree_small","Green Mushtree", REGROWTH_TYPE.EVENT, 1},
|
||||||
|
|
||||||
{"berrybush","Berry Bush",REGROWTH_TYPE.NATURAL, 4},
|
{"berrybush","Berry Bush",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.NATURAL, 4},
|
{"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.EVENT, 4},
|
||||||
{"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.NATURAL, 4},
|
{"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.EVENT, 4},
|
||||||
|
|
||||||
{"carrot_planted","Carrot",REGROWTH_TYPE.NATURAL, 1},
|
{"carrot_planted","Carrot",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower","Flower",REGROWTH_TYPE.NATURAL, 1},
|
{"flower","Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_evil","Evil Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_evil","Evil Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_cave","Light Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_cave","Light Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_cave_double","Double Light Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_cave_double","Double Light Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"flower_cave_triple","Triple Light Flower",REGROWTH_TYPE.EVENT, 1},
|
{"flower_cave_triple","Triple Light Flower",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.NATURAL, 1},
|
{"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"red_mushroom","Red Mushroom",REGROWTH_TYPE.NATURAL, 1},
|
{"red_mushroom","Red Mushroom",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"green_mushroom","Green Mushroom",REGROWTH_TYPE.NATURAL, 1},
|
{"green_mushroom","Green Mushroom",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"cactus","Cactus",REGROWTH_TYPE.NATURAL, 2},
|
{"cactus","Cactus",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"mandrake_planted","Mandrake",REGROWTH_TYPE.EVENT, 6},
|
{"mandrake_planted","Mandrake",REGROWTH_TYPE.EVENT, 6},
|
||||||
{"cave_fern","Fern",REGROWTH_TYPE.NATURAL, 1},
|
{"cave_fern","Fern",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"lichen","Lichen",REGROWTH_TYPE.NATURAL, 1},
|
{"lichen","Lichen",REGROWTH_TYPE.EVENT, 1},
|
||||||
|
|
||||||
{"reeds","Reeds",REGROWTH_TYPE.NATURAL, 2},
|
{"reeds","Reeds",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"sapling","Sapling",REGROWTH_TYPE.NATURAL, 1},
|
{"sapling","Sapling",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"grass","Grass",REGROWTH_TYPE.NATURAL, 1},
|
{"grass","Grass",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"marsh_bush","Spiky Bush",REGROWTH_TYPE.NATURAL, 2},
|
{"marsh_bush","Spiky Bush",REGROWTH_TYPE.EVENT, 2},
|
||||||
|
|
||||||
{"rock1","Boulder",REGROWTH_TYPE.NATURAL, 1},
|
{"rock1","Boulder",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"rock2","Gold Vein",REGROWTH_TYPE.NATURAL, 1},
|
{"rock2","Gold Vein",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"rock_flintless","Flintless Boulder",REGROWTH_TYPE.NATURAL, 2},
|
{"rock_flintless","Flintless Boulder",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"rock_moon","Moon Rock",REGROWTH_TYPE.NATURAL, 2},
|
{"rock_moon","Moon Rock",REGROWTH_TYPE.EVENT, 2},
|
||||||
|
|
||||||
{"stalagmite","Stalagmite",REGROWTH_TYPE.NATURAL, 1},
|
{"stalagmite","Stalagmite",REGROWTH_TYPE.EVENT, 1},
|
||||||
{"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.NATURAL, 1},
|
{"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.EVENT, 1},
|
||||||
|
|
||||||
{"rabbithole","Rabbit Hole",REGROWTH_TYPE.EVENT, 2},
|
{"rabbithole","Rabbit Hole",REGROWTH_TYPE.EVENT, 2},
|
||||||
{"beehive","Beehive",REGROWTH_TYPE.EVENT, 4},
|
{"beehive","Beehive",REGROWTH_TYPE.EVENT, 4},
|
||||||
@ -89,47 +86,30 @@ if GLOBAL.STRINGS.NAMES.MIGRATION_PORTAL then
|
|||||||
-- we have caves
|
-- we have caves
|
||||||
AddPrefabPostInit("forest", function(inst)
|
AddPrefabPostInit("forest", function(inst)
|
||||||
if inst.ismastersim then
|
if inst.ismastersim then
|
||||||
inst:AddComponent("natural_regrowth")
|
inst:AddComponent("extra_regrowth")
|
||||||
inst:AddComponent("event_regrowth")
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
AddPrefabPostInit("cave", function(inst)
|
AddPrefabPostInit("cave", function(inst)
|
||||||
if inst.ismastersim then
|
if inst.ismastersim then
|
||||||
inst:AddComponent("natural_regrowth")
|
inst:AddComponent("extra_regrowth")
|
||||||
inst:AddComponent("event_regrowth")
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
-- only overworld
|
-- only overworld
|
||||||
AddPrefabPostInit("world", function(inst)
|
AddPrefabPostInit("world", function(inst)
|
||||||
if inst.ismastersim then
|
if inst.ismastersim then
|
||||||
inst:AddComponent("natural_regrowth")
|
inst:AddComponent("extra_regrowth")
|
||||||
inst:AddComponent("event_regrowth")
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
AddComponentPostInit("natural_regrowth", function(component)
|
AddComponentPostInit("extra_regrowth", function(component)
|
||||||
for i = 1, #config_table do
|
for i = 1, #config_table do
|
||||||
local entry = config_table[i]
|
local entry = config_table[i]
|
||||||
local prefab = entry[1]
|
local prefab = entry[1]
|
||||||
if (entry[3] == REGROWTH_TYPE.NATURAL) and (GetModConfigData(prefab) ~= 0) then
|
if GetModConfigData(prefab) ~= 0 then
|
||||||
-- i % 3 - 1 = round robbin -1,0,1
|
local delay = GetModConfigData(prefab) * 240
|
||||||
local delay = GetModConfigData(prefab) * 240 + ((i % 3) - 1) * component:GetUpdatePeriod()
|
component:RegisterRegrowth(prefab, prefab, delay)
|
||||||
component:RegisterRegrowth(prefab, prefab, DEBUG and (delay / 100) or delay)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
component:FinishModConfig()
|
|
||||||
end)
|
|
||||||
|
|
||||||
AddComponentPostInit("event_regrowth", function(component)
|
|
||||||
for i = 1, #config_table do
|
|
||||||
local entry = config_table[i]
|
|
||||||
local prefab = entry[1]
|
|
||||||
if (entry[3] == REGROWTH_TYPE.EVENT) and (GetModConfigData(prefab) ~= 0) then
|
|
||||||
-- i % 3 - 1 = round robbin -1,0,1
|
|
||||||
local delay = GetModConfigData(prefab) * 240 + ((i % 3) - 1) * component:GetUpdatePeriod()
|
|
||||||
component:RegisterRegrowth(prefab, prefab, DEBUG and (delay / 100) or delay)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
component:FinishModConfig()
|
component:FinishModConfig()
|
||||||
|
@ -1,29 +1,75 @@
|
|||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
--[[ EventRegrowth class definition ]]
|
--[[ EventRegrowth class definition ]]
|
||||||
-- A modified version of the original regrowthmanager.lua
|
-- A modified and more feature-rich version of the original regrowthmanager.lua
|
||||||
-- It acts as a standalone regrowth manager and is independent of the 3 existing ones
|
-- It acts as a standalone regrowth manager and is independent of the 3 existing ones
|
||||||
-- It's unlikely affected by game updates as long as Klei doesn't change the API (they shouldn't)
|
-- It's unlikely affected by game updates as long as Klei doesn't break the API (they shouldn't)
|
||||||
-- by lolo Jan. 2018
|
-- quackerd
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
return Class(function(self, inst)
|
return Class(function(self, inst)
|
||||||
|
|
||||||
assert(inst.ismastersim, "event_regrowth should not exist on client")
|
assert(inst.ismastersim, "extra_regrowth should not exist on client")
|
||||||
|
|
||||||
require "map/terrain"
|
require "map/terrain"
|
||||||
require "wrpp_util"
|
require "ocean_util"
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
--[[ Constants ]]
|
--[[ Constants ]]
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
local DEBUG = false
|
local DEBUG = false
|
||||||
local DEBUG_TELE = false
|
local DEBUG_TELE = false
|
||||||
local UPDATE_PERIOD = 9
|
local UPDATE_PERIOD = 9 -- 9 seconds per tick
|
||||||
local JITTER_RADIUS = 6
|
local JITTER_RADIUS = 1 -- random point within this radius
|
||||||
local MAX_RADIUS = 1000
|
local MAX_RADIUS = 1000 -- cap the max radius
|
||||||
local INC_RADIUS = BASE_RADIUS / 2
|
local INC_RADIUS = 3 -- increase this amount after we fail
|
||||||
local THREADS_PER_BATCH = 3
|
local BASE_RADIUS = 15 -- don't spawn near player's base
|
||||||
local THREADS_PER_BATCH_HOOK = 5
|
local EXCLUDE_RADIUS = 2 -- no other entities in this radius within the spawn point
|
||||||
|
local MIN_PLAYER_DISTANCE = 30 -- minimum distance of player to spawn entities
|
||||||
|
|
||||||
|
local EXCLUDE_TAGS =
|
||||||
|
{
|
||||||
|
"statue", -- marble stuff on the ground, ancient statues
|
||||||
|
"hive", --spiderden, wasphive, beehive
|
||||||
|
} -- these aren't considered structures
|
||||||
|
|
||||||
|
local EXCLUDE_PREFABS =
|
||||||
|
{
|
||||||
|
catcoonden = 1,
|
||||||
|
ancient_altar = 1,
|
||||||
|
ancient_altar_broken = 1,
|
||||||
|
houndmound = 1,
|
||||||
|
mermhouse = 1,
|
||||||
|
pigtorch = 1,
|
||||||
|
mermhead = 1,
|
||||||
|
pighead = 1,
|
||||||
|
pandoraschest = 1,
|
||||||
|
minotaurchest = 1,
|
||||||
|
pighouse = 1,
|
||||||
|
rabbithouse = 1,
|
||||||
|
chessjunk1 = 1,
|
||||||
|
chessjunk2 = 1,
|
||||||
|
chessjunk3 = 1,
|
||||||
|
wall_ruins = 1,
|
||||||
|
} -- these aren't considered structures
|
||||||
|
|
||||||
|
|
||||||
|
local REGROW_STATUS =
|
||||||
|
{
|
||||||
|
SUCCESS = 0,
|
||||||
|
STRUCT = 1,
|
||||||
|
CACHE = 2,
|
||||||
|
PLAYER = 3,
|
||||||
|
DENSITY = 4,
|
||||||
|
TILE = 5,
|
||||||
|
ROAD = 6,
|
||||||
|
OCEAN = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
local CACHE_RETRY =
|
||||||
|
{
|
||||||
|
[REGROW_STATUS.PLAYER] = true,
|
||||||
|
} -- we don't increase the radius for these reasons
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
--[[ Member variables ]]
|
--[[ Member variables ]]
|
||||||
@ -33,13 +79,91 @@ return Class(function(self, inst)
|
|||||||
self.inst = inst
|
self.inst = inst
|
||||||
|
|
||||||
--Private
|
--Private
|
||||||
local regrowth_table_populated_by_mod = false
|
local ready = false
|
||||||
local regrowth_table = {}
|
local regrowth_table = {}
|
||||||
local entity_list = {}
|
local entity_list = {}
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
--[[ Private member functions ]]
|
--[[ Private member functions ]]
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
local function TestStructures(x, y, z, radius)
|
||||||
|
local ents = TheSim:FindEntities(x,y,z, BASE_RADIUS, nil, EXCLUDE_TAGS, { "structure", "wall" })
|
||||||
|
|
||||||
|
for i, v in ipairs(ents) do
|
||||||
|
if EXCLUDE_PREFABS[v.prefab] == nil then
|
||||||
|
-- if we cannot find it from the exclude table, then it is a structure and we failed the test
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function CanPlaceAtPoint(x, y, z)
|
||||||
|
local tile = TheWorld.Map:GetTileAtPoint(x, y, z)
|
||||||
|
return tile ~= GROUND.IMPASSABLE and
|
||||||
|
tile ~= GROUND.INVALID and
|
||||||
|
not GROUND_FLOORING[tile]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function TestPlayers(x, y, z, radius)
|
||||||
|
return not IsAnyPlayerInRange(x,y,z, MIN_PLAYER_DISTANCE, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function TestEntities(x, y, z, radius)
|
||||||
|
local ents = TheSim:FindEntities(x,y,z, EXCLUDE_RADIUS)
|
||||||
|
return not (#ents > 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function TestRegrowth(x, y, z, prefab, tile)
|
||||||
|
local cur_tile = TheWorld.Map:GetTileAtPoint(x, y, z)
|
||||||
|
|
||||||
|
if not TestPlayers(x,y,z, MIN_PLAYER_DISTANCE) then
|
||||||
|
return REGROW_STATUS.PLAYER
|
||||||
|
end
|
||||||
|
|
||||||
|
if not TestStructures(x, y, z, BASE_RADIUS) then
|
||||||
|
-- No regrowth around players and their bases
|
||||||
|
return REGROW_STATUS.STRUCT
|
||||||
|
end
|
||||||
|
|
||||||
|
if not TestEntities(x,y,z, EXCLUDE_RADIUS) then
|
||||||
|
-- Too dense
|
||||||
|
return REGROW_STATUS.DENSITY
|
||||||
|
end
|
||||||
|
|
||||||
|
if (RoadManager ~= nil) and (RoadManager:IsOnRoad(x, 0, z)) then
|
||||||
|
return REGROW_STATUS.ROAD
|
||||||
|
end
|
||||||
|
|
||||||
|
-- hack to get away with it for now
|
||||||
|
if IsOceanTile(cur_tile) then
|
||||||
|
return REGROW_STATUS.OCEAN
|
||||||
|
end
|
||||||
|
|
||||||
|
if (CanPlaceAtPoint(x, y, z) and TheWorld.Map:CanPlacePrefabFilteredAtPoint(x, y, z, prefab)) or ((tile ~= nil) and (cur_tile == tile)) then
|
||||||
|
return REGROW_STATUS.SUCCESS
|
||||||
|
end
|
||||||
|
|
||||||
|
return REGROW_STATUS.TILE
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetPosStr(pos)
|
||||||
|
return "( " .. pos.x .. " , " .. pos.y .. " , ".. pos.z .. " )"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetCoordStr(x,y,z)
|
||||||
|
return "( " .. x .. " , " .. y .. " , ".. z .. " )"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function GetRStatusStr(status)
|
||||||
|
for k, v in pairs(REGROW_STATUS) do
|
||||||
|
if v == status then
|
||||||
|
return k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local function EntityDeathEventHandler(ent)
|
local function EntityDeathEventHandler(ent)
|
||||||
if entity_list[ent.prefab] == nil then
|
if entity_list[ent.prefab] == nil then
|
||||||
@ -57,7 +181,7 @@ return Class(function(self, inst)
|
|||||||
ent:RemoveEventCallback("onremove", EntityDeathEventHandler, nil)
|
ent:RemoveEventCallback("onremove", EntityDeathEventHandler, nil)
|
||||||
|
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] " .. ent.prefab .. " was removed at " .. GetPosStr(position) .. " Tile: " .. TheWorld.Map:GetTileAtPoint(position.x, position.y, position.z))
|
print("[ExtraRegrowth] " .. ent.prefab .. " was removed at " .. GetPosStr(position) .. " Tile: " .. TheWorld.Map:GetTileAtPoint(position.x, position.y, position.z))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -75,16 +199,16 @@ return Class(function(self, inst)
|
|||||||
local orig_tile = inst.Map:GetTileAtPoint(position.x, position.y, position.z)
|
local orig_tile = inst.Map:GetTileAtPoint(position.x, position.y, position.z)
|
||||||
local status = TestRegrowth(x,y,z, prefab, orig_tile)
|
local status = TestRegrowth(x,y,z, prefab, orig_tile)
|
||||||
|
|
||||||
if status == REGROW_STATUS.STRUCT then
|
if CACHE_RETRY[status] ~= nil then
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Failed to spawn a product " .. product .. " at " .. GetCoordStr(x,y,z) .. " for prefab " .. prefab .. " at " .. GetPosStr(position) .. " with rand radius " .. rand_radius .. " due to " .. GetRStatusStr(status))
|
print("[ExtraRegrowth] Cached a " .. product .. " at " .. GetCoordStr(x,y,z) .. " for " .. prefab .. " at " .. GetPosStr(position) .. " with radius " .. rand_radius .. " due to " .. GetRStatusStr(status))
|
||||||
end
|
end
|
||||||
return status
|
return status
|
||||||
end
|
end
|
||||||
|
|
||||||
if status ~= REGROW_STATUS.SUCCESS then
|
if status ~= REGROW_STATUS.SUCCESS then
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Cached a product " .. product .. " at ".. GetCoordStr(x,y,z) .. " for prefab " .. prefab .. " at " .. GetPosStr(position) .. " with rand radius ".. rand_radius .. " due to " .. GetRStatusStr(status))
|
print("[ExtraRegrowth] Failed to spawn a " .. product .. " at ".. GetCoordStr(x,y,z) .. " for " .. prefab .. " at " .. GetPosStr(position) .. " with radius ".. rand_radius .. " due to " .. GetRStatusStr(status))
|
||||||
end
|
end
|
||||||
return status
|
return status
|
||||||
end
|
end
|
||||||
@ -95,7 +219,7 @@ return Class(function(self, inst)
|
|||||||
instance:ListenForEvent("onremove", EntityDeathEventHandler, nil)
|
instance:ListenForEvent("onremove", EntityDeathEventHandler, nil)
|
||||||
|
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Spawned a product " .. product .. " at " .. GetCoordStr(x,y,z) .. " for prefab " .. prefab .. " at " .. GetPosStr(position) .. " with rand radius " .. rand_radius)
|
print("[ExtraRegrowth] Spawned a " .. product .. " at " .. GetCoordStr(x,y,z) .. " for " .. prefab .. " at " .. GetPosStr(position) .. " with radius " .. rand_radius .. " tile: " .. TheWorld.Map:GetTileAtPoint(x,y,z))
|
||||||
end
|
end
|
||||||
|
|
||||||
if DEBUG_TELE then
|
if DEBUG_TELE then
|
||||||
@ -120,20 +244,23 @@ return Class(function(self, inst)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Hooked " .. count .. " " .. prefab)
|
print("[ExtraRegrowth] Hooked " .. count .. " " .. prefab)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function HookAllEntities(ents)
|
local function HookAllRegisteredPrefabs()
|
||||||
local count = 0
|
local count = 0
|
||||||
local delay = 0
|
for guid,ent in pairs(Ents) do
|
||||||
for prefab in pairs(ents) do
|
if regrowth_table[ent.prefab] ~= nil then
|
||||||
inst:DoTaskInTime(delay, function() HookEntities(prefab) end)
|
ent:RemoveEventCallback("onremove", EntityDeathEventHandler, nil)
|
||||||
|
ent:ListenForEvent("onremove", EntityDeathEventHandler, nil)
|
||||||
count = count + 1
|
count = count + 1
|
||||||
if math.fmod(count, THREADS_PER_BATCH_HOOK) == 0 then
|
|
||||||
delay = delay + 1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if DEBUG then
|
||||||
|
print("[ExtraRegrowth] Hooked " .. count .. " entities")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
@ -144,18 +271,23 @@ return Class(function(self, inst)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function self:FinishModConfig()
|
function self:FinishModConfig()
|
||||||
regrowth_table_populated_by_mod = true
|
HookAllRegisteredPrefabs()
|
||||||
|
ready = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function self:RegisterRegrowth(prefab, product, interval)
|
function self:RegisterRegrowth(prefab, product, interval)
|
||||||
|
|
||||||
if interval == nil then
|
if interval == nil then
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] WARNING: interval for prefab " .. prefab .. " is null. Using default.")
|
print("[ExtraRegrowth] WARNING: interval for prefab " .. prefab .. " is null. Using default.")
|
||||||
end
|
end
|
||||||
interval = 480
|
interval = 480
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if DEBUG then
|
||||||
|
interval = interval / 100
|
||||||
|
end
|
||||||
|
|
||||||
if regrowth_table[prefab] == nil then
|
if regrowth_table[prefab] == nil then
|
||||||
-- avoid duplicate registration
|
-- avoid duplicate registration
|
||||||
regrowth_table[prefab] =
|
regrowth_table[prefab] =
|
||||||
@ -164,21 +296,19 @@ return Class(function(self, inst)
|
|||||||
interval = interval
|
interval = interval
|
||||||
}
|
}
|
||||||
|
|
||||||
HookEntities(prefab)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Registered product " .. product .. " for prefab " .. prefab .. " with interval " .. interval)
|
print("[ExtraRegrowth] Registered product " .. product .. " for prefab " .. prefab .. " with interval " .. interval)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
--[[ Initialization ]]
|
--[[ Initialization ]]
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
inst:DoTaskInTime(0, function() HookAllRegisteredPrefabs() end)
|
||||||
inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate(UPDATE_PERIOD) end)
|
inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate() end)
|
||||||
inst:ListenForEvent("ms_cyclecomplete", function() HookAllEntities(regrowth_table) end) -- every ~ 1 day we rehook every entities
|
inst:ListenForEvent("ms_cyclecomplete", function() HookAllRegisteredPrefabs() end) -- every ~ 1 day we rehook every entities
|
||||||
inst:DoTaskInTime(0, function() HookAllEntities(regrowth_table) end)
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
--[[ Update ]]
|
--[[ Update ]]
|
||||||
@ -195,21 +325,20 @@ return Class(function(self, inst)
|
|||||||
data.remove = true
|
data.remove = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if success == REGROW_STATUS.STRUCT then
|
if CACHE_RETRY[success] == nil then
|
||||||
-- only increase radius when there are structures nearby
|
-- only increase radius when not cached
|
||||||
data.retry = data.retry + 1
|
data.retry = data.retry + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function self:LongUpdate(dt)
|
function self:LongUpdate()
|
||||||
if not regrowth_table_populated_by_mod then
|
if not ready then
|
||||||
-- do nothing if the table is not fully initialized
|
-- 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
|
-- in case we accidentally drop some saved entities due to the respawn_table[prefab] == nil check
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local count = 0
|
local count = 0
|
||||||
local delay = 0
|
|
||||||
for prefab in pairs(entity_list) do
|
for prefab in pairs(entity_list) do
|
||||||
if entity_list[prefab] == nil or #entity_list[prefab] == 0 then
|
if entity_list[prefab] == nil or #entity_list[prefab] == 0 then
|
||||||
-- only do meaningful work
|
-- only do meaningful work
|
||||||
@ -222,7 +351,7 @@ return Class(function(self, inst)
|
|||||||
if entity_list[prefab][i].remove then
|
if entity_list[prefab][i].remove then
|
||||||
-- handle expired objects first
|
-- handle expired objects first
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Removed prefab " .. prefab .. " at ".. GetPosStr(entity_list[prefab][i].position) .." from the entity list.")
|
print("[ExtraRegrowth] Removed prefab " .. prefab .. " at ".. GetPosStr(entity_list[prefab][i].position) .." from the entity list.")
|
||||||
end
|
end
|
||||||
table.remove(entity_list[prefab], i)
|
table.remove(entity_list[prefab], i)
|
||||||
else
|
else
|
||||||
@ -235,19 +364,14 @@ return Class(function(self, inst)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Prefab " .. prefab .. " at " .. GetPosStr(entity_list[prefab][i].position) .. " has interval " .. entity_list[prefab][i].interval )
|
print("[ExtraRegrowth] Prefab " .. prefab .. " at " .. GetPosStr(entity_list[prefab][i].position) .. " has interval " .. entity_list[prefab][i].interval )
|
||||||
end
|
end
|
||||||
|
|
||||||
if entity_list[prefab][i].interval == 0 then
|
if entity_list[prefab][i].interval == 0 then
|
||||||
-- different threads
|
-- different threads
|
||||||
local data = entity_list[prefab][i]
|
local data = entity_list[prefab][i]
|
||||||
inst:DoTaskInTime(delay, function() RegrowPrefabTask(prefab, data) end)
|
|
||||||
|
|
||||||
-- try not to flood the server with threads
|
RegrowPrefabTask(prefab, data)
|
||||||
count = count + 1
|
|
||||||
if math.fmod( count,THREADS_PER_BATCH ) == 0 then
|
|
||||||
delay = delay + 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -283,7 +407,7 @@ return Class(function(self, inst)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Saved " .. #data.entities[prefab] .. " entities for prefab " .. prefab)
|
print("[ExtraRegrowth] Saved " .. #data.entities[prefab] .. " entities for prefab " .. prefab)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -309,7 +433,7 @@ return Class(function(self, inst)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
print("[EventRegrowth] Loaded " .. #entity_list[prefab] .. " entities for prefab " .. prefab)
|
print("[ExtraRegrowth] Loaded " .. #entity_list[prefab] .. " entities for prefab " .. prefab)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -1,281 +0,0 @@
|
|||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ NaturalRegrowth class definition ]]
|
|
||||||
-- A modified version of the original desolationspawner.lua
|
|
||||||
-- It acts as a standalone regrowth manager and is independent of the 3 existing ones
|
|
||||||
-- It's unlikely affected by game updates as long as Klei doesn't change the API (they shouldn't)
|
|
||||||
-- by lolo Jan. 2018
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
return Class(function(self, inst)
|
|
||||||
|
|
||||||
assert(inst.ismastersim, "natural_regrowth should not exist on client")
|
|
||||||
|
|
||||||
require "map/terrain"
|
|
||||||
require "wrpp_util"
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Constants ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
local DEBUG = false
|
|
||||||
local DEBUG_TELE = false
|
|
||||||
local UPDATE_PERIOD = 11
|
|
||||||
local THREADS_PER_BATCH = 3
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Member variables ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--Public
|
|
||||||
self.inst = inst
|
|
||||||
|
|
||||||
--Private
|
|
||||||
local regrowth_table = {}
|
|
||||||
local area_data = {}
|
|
||||||
local intervals = {}
|
|
||||||
local regrowth_table_populated_by_mod = false
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Private member functions ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local function TryRegrowth(x, y, z , prefab, product)
|
|
||||||
local status = TestRegrowth(x,0,z, product, nil)
|
|
||||||
if status == REGROW_STATUS.SUCCESS then
|
|
||||||
local instance = SpawnPrefab(product)
|
|
||||||
|
|
||||||
if instance ~= nil then
|
|
||||||
instance.Transform:SetPosition(x,0,z)
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Spawned a product " .. product .. " at " .. GetCoordStr(x,0,z) .. " for prefab " .. prefab)
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG_TELE then
|
|
||||||
c_teleport(x,0,z)
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Failed to spawn a product " .. product .. " at " .. GetCoordStr(x,0,z) .. " for prefab " .. prefab .. " due to " .. GetRStatusStr(status))
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function PrintDensities()
|
|
||||||
for area, densities in pairs(inst.generated.densities) do
|
|
||||||
for k,v in pairs(densities) do
|
|
||||||
print(area, k, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function PopulateAreaData(prefab)
|
|
||||||
if inst.generated == nil then
|
|
||||||
-- Still starting up
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if area_data[prefab] ~= nil then
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Already populated prefab " .. 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
|
|
||||||
if v == area then
|
|
||||||
if area_data[prefab] == nil then
|
|
||||||
area_data[prefab] = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
area_data[prefab][#area_data[prefab] + 1] = id
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Populated " .. (area_data[prefab] == nil and 0 or #area_data[prefab]) .. " areas for prefab " .. prefab)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function PopulateAllAreaData()
|
|
||||||
-- This has to be run after 1 frame from startup
|
|
||||||
for prefab in pairs(regrowth_table) do
|
|
||||||
PopulateAreaData(prefab)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Public member functions ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
function self:GetUpdatePeriod()
|
|
||||||
return UPDATE_PERIOD
|
|
||||||
end
|
|
||||||
|
|
||||||
function self:FinishModConfig()
|
|
||||||
regrowth_table_populated_by_mod = true
|
|
||||||
end
|
|
||||||
|
|
||||||
function self:RegisterRegrowth(prefab, product, interval)
|
|
||||||
|
|
||||||
if interval == nil then
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] WARNING: interval for prefab " .. prefab .. " is null. Using default.")
|
|
||||||
end
|
|
||||||
interval = 480
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Registered product " .. product .. " for prefab " .. prefab .. " with interval " .. interval)
|
|
||||||
end
|
|
||||||
regrowth_table[prefab] = {product = product, interval = interval}
|
|
||||||
|
|
||||||
if intervals[prefab] == nil then
|
|
||||||
intervals[prefab] = interval
|
|
||||||
end
|
|
||||||
|
|
||||||
PopulateAreaData(prefab)
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Initialization ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate(UPDATE_PERIOD) end)
|
|
||||||
|
|
||||||
inst:DoTaskInTime(0, PopulateAllAreaData)
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Update ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local function RegrowPrefabTask(areas, prefab)
|
|
||||||
local success = false
|
|
||||||
local rand = math.random(1, #areas)
|
|
||||||
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
|
|
||||||
end
|
|
||||||
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
|
|
||||||
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
|
|
||||||
if intervals[prefab] > UPDATE_PERIOD then
|
|
||||||
intervals[prefab] = intervals[prefab] - UPDATE_PERIOD
|
|
||||||
else
|
|
||||||
intervals[prefab] = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Prefab " .. prefab .. " has interval " .. intervals[prefab])
|
|
||||||
end
|
|
||||||
|
|
||||||
if intervals[prefab] == 0 then
|
|
||||||
local area = area_data[prefab]
|
|
||||||
-- use multiple threads? In the future a threadpool maybe?
|
|
||||||
inst:DoTaskInTime(delay, function() RegrowPrefabTask(area, 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
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ Save/Load ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function self:OnSave()
|
|
||||||
local data = {
|
|
||||||
areas = {},
|
|
||||||
intervals = {}
|
|
||||||
}
|
|
||||||
for prefab in pairs(area_data) do
|
|
||||||
data.areas[prefab] = {}
|
|
||||||
|
|
||||||
for i = 1, #area_data[prefab] do
|
|
||||||
data.areas[prefab][#data.areas[prefab] + 1] = area_data[prefab][i]
|
|
||||||
end
|
|
||||||
|
|
||||||
if DEBUG then
|
|
||||||
print("[NaturalRegrowth] Saved " .. #data.areas[prefab] .. " areas for prefab " .. prefab)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for prefab, interval in pairs(intervals) do
|
|
||||||
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 " .. 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] = {}
|
|
||||||
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 " .. 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 " .. prefab)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
--[[ End ]]
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
end)
|
|
@ -1,109 +0,0 @@
|
|||||||
EXCLUDE_TAGS =
|
|
||||||
{
|
|
||||||
"statue", -- marble stuff on the ground, ancient statues
|
|
||||||
"hive", --spiderden, wasphive, beehive
|
|
||||||
}
|
|
||||||
|
|
||||||
EXCLUDE_PREFABS =
|
|
||||||
{
|
|
||||||
catcoonden = 1,
|
|
||||||
ancient_altar = 1,
|
|
||||||
ancient_altar_broken = 1,
|
|
||||||
houndmound = 1,
|
|
||||||
mermhouse = 1,
|
|
||||||
pigtorch = 1,
|
|
||||||
mermhead = 1,
|
|
||||||
pighead = 1,
|
|
||||||
pandoraschest = 1,
|
|
||||||
minotaurchest = 1,
|
|
||||||
pighouse = 1,
|
|
||||||
rabbithouse = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE_RADIUS = 20
|
|
||||||
EXCLUDE_RADIUS = 2
|
|
||||||
MIN_PLAYER_DISTANCE = 40
|
|
||||||
|
|
||||||
REGROW_STATUS =
|
|
||||||
{
|
|
||||||
SUCCESS = 0,
|
|
||||||
STRUCT = 1,
|
|
||||||
CACHE = 2,
|
|
||||||
PLAYER = 3,
|
|
||||||
DENSITY = 4,
|
|
||||||
TILE = 5,
|
|
||||||
ROAD = 6
|
|
||||||
}
|
|
||||||
|
|
||||||
local function TestStructures(x, y, z, radius)
|
|
||||||
local ents = TheSim:FindEntities(x,y,z, BASE_RADIUS, nil, EXCLUDE_TAGS, { "structure", "wall" })
|
|
||||||
|
|
||||||
for i, v in ipairs(ents) do
|
|
||||||
if EXCLUDE_PREFABS[v.prefab] == nil then
|
|
||||||
-- if we cannot find it from the exclude table, then it is a structure and we failed the test
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function CanPlaceAtPoint(x, y, z)
|
|
||||||
local tile = TheWorld.Map:GetTileAtPoint(x, y, z)
|
|
||||||
return tile ~= GROUND.IMPASSABLE and
|
|
||||||
tile ~= GROUND.INVALID and
|
|
||||||
not GROUND_FLOORING[tile]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function TestPlayers(x, y, z, radius)
|
|
||||||
return not IsAnyPlayerInRange(x,y,z, MIN_PLAYER_DISTANCE, nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function TestEntities(x, y, z, radius)
|
|
||||||
local ents = TheSim:FindEntities(x,y,z, EXCLUDE_RADIUS)
|
|
||||||
return not (#ents > 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
function TestRegrowth(x, y, z, prefab, tile)
|
|
||||||
|
|
||||||
if not TestPlayers(x,y,z, MIN_PLAYER_DISTANCE) then
|
|
||||||
return REGROW_STATUS.PLAYER
|
|
||||||
end
|
|
||||||
|
|
||||||
if not TestStructures(x, y, z, BASE_RADIUS) then
|
|
||||||
-- No regrowth around players and their bases
|
|
||||||
return REGROW_STATUS.STRUCT
|
|
||||||
end
|
|
||||||
|
|
||||||
if not TestEntities(x,y,z, EXCLUDE_RADIUS) then
|
|
||||||
-- Too dense
|
|
||||||
return REGROW_STATUS.DENSITY
|
|
||||||
end
|
|
||||||
|
|
||||||
if (RoadManager ~= nil) and (RoadManager:IsOnRoad(x, 0, z)) then
|
|
||||||
return REGROW_STATUS.ROAD
|
|
||||||
end
|
|
||||||
|
|
||||||
if (CanPlaceAtPoint(x, y, z) and TheWorld.Map:CanPlacePrefabFilteredAtPoint(x, y, z, prefab)) or ((tile ~= nil) and (TheWorld.Map:GetTileAtPoint(x, y, z) == tile)) then
|
|
||||||
return REGROW_STATUS.SUCCESS
|
|
||||||
end
|
|
||||||
|
|
||||||
return REGROW_STATUS.TILE
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetPosStr(pos)
|
|
||||||
return "( " .. pos.x .. " , " .. pos.y .. " , ".. pos.z .. " )"
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetCoordStr(x,y,z)
|
|
||||||
return "( " .. x .. " , " .. y .. " , ".. z .. " )"
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetRStatusStr(status)
|
|
||||||
for k, v in pairs(REGROW_STATUS) do
|
|
||||||
if v == status then
|
|
||||||
return k
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
Loading…
Reference in New Issue
Block a user