From 4e4cf915cd553b16f9d7d47845b0cb1249c40c74 Mon Sep 17 00:00:00 2001 From: quackerd Date: Sun, 27 Oct 2019 04:52:14 -0400 Subject: [PATCH] Ver 2.0 with ocean support --- src/modinfo.lua | 63 ++-- src/modmain.lua | 96 +++--- ...{event_regrowth.lua => extra_regrowth.lua} | 220 +++++++++++--- src/scripts/components/natural_regrowth.lua | 281 ------------------ src/scripts/wrpp_util.lua | 109 ------- 5 files changed, 241 insertions(+), 528 deletions(-) rename src/scripts/components/{event_regrowth.lua => extra_regrowth.lua} (60%) delete mode 100644 src/scripts/components/natural_regrowth.lua delete mode 100644 src/scripts/wrpp_util.lua diff --git a/src/modinfo.lua b/src/modinfo.lua index d189a7f..de3a867 100644 --- a/src/modinfo.lua +++ b/src/modinfo.lua @@ -1,6 +1,6 @@ name = "World Regrowth++" -version = "1.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!" +version = "2.0" +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" forumthread = "" @@ -16,54 +16,53 @@ dst_compatible = true local REGROWTH_TYPE = { - NATURAL = 1, - EVENT = 2 + EVENT = 1 } -- Configuration Generation -- I can't reference this from another file... duplicate local config_table = { - {"evergreen","Evergreen", REGROWTH_TYPE.NATURAL, 1}, - {"deciduoustree","Birchnut Tree",REGROWTH_TYPE.NATURAL, 1}, - {"marsh_tree","Spiky Tree",REGROWTH_TYPE.NATURAL, 2}, - {"twiggytree","Twiggy Tree",REGROWTH_TYPE.NATURAL, 2}, + {"evergreen","Evergreen", REGROWTH_TYPE.EVENT, 1}, + {"deciduoustree","Birchnut Tree",REGROWTH_TYPE.EVENT, 1}, + {"marsh_tree","Spiky Tree",REGROWTH_TYPE.EVENT, 2}, + {"twiggytree","Twiggy Tree",REGROWTH_TYPE.EVENT, 2}, {"marbletree","Marble Tree",REGROWTH_TYPE.EVENT, 4}, {"livingtree","Totally Normal Tree",REGROWTH_TYPE.EVENT, 4}, - {"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.NATURAL, 1}, - {"mushtree_medium","Red Mushtree",REGROWTH_TYPE.NATURAL, 1}, - {"mushtree_small","Green Mushtree", REGROWTH_TYPE.NATURAL, 1}, + {"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.EVENT, 1}, + {"mushtree_medium","Red Mushtree",REGROWTH_TYPE.EVENT, 1}, + {"mushtree_small","Green Mushtree", REGROWTH_TYPE.EVENT, 1}, - {"berrybush","Berry Bush",REGROWTH_TYPE.NATURAL, 4}, - {"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.NATURAL, 4}, - {"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.NATURAL, 4}, + {"berrybush","Berry Bush",REGROWTH_TYPE.EVENT, 4}, + {"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.EVENT, 4}, + {"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.EVENT, 4}, - {"carrot_planted","Carrot",REGROWTH_TYPE.NATURAL, 1}, - {"flower","Flower",REGROWTH_TYPE.NATURAL, 1}, + {"carrot_planted","Carrot",REGROWTH_TYPE.EVENT, 1}, + {"flower","Flower",REGROWTH_TYPE.EVENT, 1}, {"flower_evil","Evil 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_triple","Triple Light Flower",REGROWTH_TYPE.EVENT, 1}, - {"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.NATURAL, 1}, - {"red_mushroom","Red Mushroom",REGROWTH_TYPE.NATURAL, 1}, - {"green_mushroom","Green Mushroom",REGROWTH_TYPE.NATURAL, 1}, - {"cactus","Cactus",REGROWTH_TYPE.NATURAL, 2}, + {"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.EVENT, 1}, + {"red_mushroom","Red Mushroom",REGROWTH_TYPE.EVENT, 1}, + {"green_mushroom","Green Mushroom",REGROWTH_TYPE.EVENT, 1}, + {"cactus","Cactus",REGROWTH_TYPE.EVENT, 2}, {"mandrake_planted","Mandrake",REGROWTH_TYPE.EVENT, 6}, - {"cave_fern","Fern",REGROWTH_TYPE.NATURAL, 1}, - {"lichen","Lichen",REGROWTH_TYPE.NATURAL, 1}, + {"cave_fern","Fern",REGROWTH_TYPE.EVENT, 1}, + {"lichen","Lichen",REGROWTH_TYPE.EVENT, 1}, - {"reeds","Reeds",REGROWTH_TYPE.NATURAL, 2}, - {"sapling","Sapling",REGROWTH_TYPE.NATURAL, 1}, - {"grass","Grass",REGROWTH_TYPE.NATURAL, 1}, - {"marsh_bush","Spiky Bush",REGROWTH_TYPE.NATURAL, 2}, + {"reeds","Reeds",REGROWTH_TYPE.EVENT, 2}, + {"sapling","Sapling",REGROWTH_TYPE.EVENT, 1}, + {"grass","Grass",REGROWTH_TYPE.EVENT, 1}, + {"marsh_bush","Spiky Bush",REGROWTH_TYPE.EVENT, 2}, - {"rock1","Boulder",REGROWTH_TYPE.NATURAL, 1}, - {"rock2","Gold Vein",REGROWTH_TYPE.NATURAL, 1}, - {"rock_flintless","Flintless Boulder",REGROWTH_TYPE.NATURAL, 2}, - {"rock_moon","Moon Rock",REGROWTH_TYPE.NATURAL, 2}, + {"rock1","Boulder",REGROWTH_TYPE.EVENT, 1}, + {"rock2","Gold Vein",REGROWTH_TYPE.EVENT, 1}, + {"rock_flintless","Flintless Boulder",REGROWTH_TYPE.EVENT, 2}, + {"rock_moon","Moon Rock",REGROWTH_TYPE.EVENT, 2}, - {"stalagmite","Stalagmite",REGROWTH_TYPE.NATURAL, 1}, - {"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.NATURAL, 1}, + {"stalagmite","Stalagmite",REGROWTH_TYPE.EVENT, 1}, + {"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.EVENT, 1}, {"rabbithole","Rabbit Hole",REGROWTH_TYPE.EVENT, 2}, {"beehive","Beehive",REGROWTH_TYPE.EVENT, 4}, diff --git a/src/modmain.lua b/src/modmain.lua index d4db156..468a1f5 100644 --- a/src/modmain.lua +++ b/src/modmain.lua @@ -1,55 +1,52 @@ local REGROWTH_TYPE = { - NATURAL = 1, - EVENT = 2 + EVENT = 1 } -local DEBUG = false - -- Configuration Generation -- I can't reference this from another file... duplicate local config_table = { - {"evergreen","Evergreen", REGROWTH_TYPE.NATURAL, 1}, - {"deciduoustree","Birchnut Tree",REGROWTH_TYPE.NATURAL, 1}, - {"marsh_tree","Spiky Tree",REGROWTH_TYPE.NATURAL, 2}, - {"twiggytree","Twiggy Tree",REGROWTH_TYPE.NATURAL, 2}, + {"evergreen","Evergreen", REGROWTH_TYPE.EVENT, 1}, + {"deciduoustree","Birchnut Tree",REGROWTH_TYPE.EVENT, 1}, + {"marsh_tree","Spiky Tree",REGROWTH_TYPE.EVENT, 2}, + {"twiggytree","Twiggy Tree",REGROWTH_TYPE.EVENT, 2}, {"marbletree","Marble Tree",REGROWTH_TYPE.EVENT, 4}, {"livingtree","Totally Normal Tree",REGROWTH_TYPE.EVENT, 4}, - {"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.NATURAL, 1}, - {"mushtree_medium","Red Mushtree",REGROWTH_TYPE.NATURAL, 1}, - {"mushtree_small","Green Mushtree", REGROWTH_TYPE.NATURAL, 1}, + {"mushtree_tall","Blue Mushtree", REGROWTH_TYPE.EVENT, 1}, + {"mushtree_medium","Red Mushtree",REGROWTH_TYPE.EVENT, 1}, + {"mushtree_small","Green Mushtree", REGROWTH_TYPE.EVENT, 1}, - {"berrybush","Berry Bush",REGROWTH_TYPE.NATURAL, 4}, - {"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.NATURAL, 4}, - {"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.NATURAL, 4}, + {"berrybush","Berry Bush",REGROWTH_TYPE.EVENT, 4}, + {"berrybush2","Spiky Berry Bush",REGROWTH_TYPE.EVENT, 4}, + {"berrybush_juicy","Juicy Berry Bush",REGROWTH_TYPE.EVENT, 4}, - {"carrot_planted","Carrot",REGROWTH_TYPE.NATURAL, 1}, - {"flower","Flower",REGROWTH_TYPE.NATURAL, 1}, + {"carrot_planted","Carrot",REGROWTH_TYPE.EVENT, 1}, + {"flower","Flower",REGROWTH_TYPE.EVENT, 1}, {"flower_evil","Evil 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_triple","Triple Light Flower",REGROWTH_TYPE.EVENT, 1}, - {"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.NATURAL, 1}, - {"red_mushroom","Red Mushroom",REGROWTH_TYPE.NATURAL, 1}, - {"green_mushroom","Green Mushroom",REGROWTH_TYPE.NATURAL, 1}, - {"cactus","Cactus",REGROWTH_TYPE.NATURAL, 2}, + {"blue_mushroom","Blue Mushroom",REGROWTH_TYPE.EVENT, 1}, + {"red_mushroom","Red Mushroom",REGROWTH_TYPE.EVENT, 1}, + {"green_mushroom","Green Mushroom",REGROWTH_TYPE.EVENT, 1}, + {"cactus","Cactus",REGROWTH_TYPE.EVENT, 2}, {"mandrake_planted","Mandrake",REGROWTH_TYPE.EVENT, 6}, - {"cave_fern","Fern",REGROWTH_TYPE.NATURAL, 1}, - {"lichen","Lichen",REGROWTH_TYPE.NATURAL, 1}, + {"cave_fern","Fern",REGROWTH_TYPE.EVENT, 1}, + {"lichen","Lichen",REGROWTH_TYPE.EVENT, 1}, - {"reeds","Reeds",REGROWTH_TYPE.NATURAL, 2}, - {"sapling","Sapling",REGROWTH_TYPE.NATURAL, 1}, - {"grass","Grass",REGROWTH_TYPE.NATURAL, 1}, - {"marsh_bush","Spiky Bush",REGROWTH_TYPE.NATURAL, 2}, + {"reeds","Reeds",REGROWTH_TYPE.EVENT, 2}, + {"sapling","Sapling",REGROWTH_TYPE.EVENT, 1}, + {"grass","Grass",REGROWTH_TYPE.EVENT, 1}, + {"marsh_bush","Spiky Bush",REGROWTH_TYPE.EVENT, 2}, - {"rock1","Boulder",REGROWTH_TYPE.NATURAL, 1}, - {"rock2","Gold Vein",REGROWTH_TYPE.NATURAL, 1}, - {"rock_flintless","Flintless Boulder",REGROWTH_TYPE.NATURAL, 2}, - {"rock_moon","Moon Rock",REGROWTH_TYPE.NATURAL, 2}, + {"rock1","Boulder",REGROWTH_TYPE.EVENT, 1}, + {"rock2","Gold Vein",REGROWTH_TYPE.EVENT, 1}, + {"rock_flintless","Flintless Boulder",REGROWTH_TYPE.EVENT, 2}, + {"rock_moon","Moon Rock",REGROWTH_TYPE.EVENT, 2}, - {"stalagmite","Stalagmite",REGROWTH_TYPE.NATURAL, 1}, - {"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.NATURAL, 1}, + {"stalagmite","Stalagmite",REGROWTH_TYPE.EVENT, 1}, + {"stalagmite_tall","Tall Stalagmite",REGROWTH_TYPE.EVENT, 1}, {"rabbithole","Rabbit Hole",REGROWTH_TYPE.EVENT, 2}, {"beehive","Beehive",REGROWTH_TYPE.EVENT, 4}, @@ -89,48 +86,31 @@ if GLOBAL.STRINGS.NAMES.MIGRATION_PORTAL then -- we have caves AddPrefabPostInit("forest", function(inst) if inst.ismastersim then - inst:AddComponent("natural_regrowth") - inst:AddComponent("event_regrowth") + inst:AddComponent("extra_regrowth") end end) AddPrefabPostInit("cave", function(inst) if inst.ismastersim then - inst:AddComponent("natural_regrowth") - inst:AddComponent("event_regrowth") + inst:AddComponent("extra_regrowth") end end) else -- only overworld AddPrefabPostInit("world", function(inst) if inst.ismastersim then - inst:AddComponent("natural_regrowth") - inst:AddComponent("event_regrowth") + inst:AddComponent("extra_regrowth") end end) end -AddComponentPostInit("natural_regrowth", function(component) +AddComponentPostInit("extra_regrowth", function(component) for i = 1, #config_table do local entry = config_table[i] local prefab = entry[1] - if (entry[3] == REGROWTH_TYPE.NATURAL) 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) + if GetModConfigData(prefab) ~= 0 then + local delay = GetModConfigData(prefab) * 240 + component:RegisterRegrowth(prefab, prefab, delay) end - end - component:FinishModConfig() + 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 - component:FinishModConfig() -end) \ No newline at end of file diff --git a/src/scripts/components/event_regrowth.lua b/src/scripts/components/extra_regrowth.lua similarity index 60% rename from src/scripts/components/event_regrowth.lua rename to src/scripts/components/extra_regrowth.lua index 36417f0..bc2b40f 100644 --- a/src/scripts/components/event_regrowth.lua +++ b/src/scripts/components/extra_regrowth.lua @@ -1,29 +1,75 @@ -------------------------------------------------------------------------- --[[ 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's unlikely affected by game updates as long as Klei doesn't change the API (they shouldn't) --- by lolo Jan. 2018 +-- It's unlikely affected by game updates as long as Klei doesn't break the API (they shouldn't) +-- quackerd -------------------------------------------------------------------------- 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 "wrpp_util" + require "ocean_util" -------------------------------------------------------------------------- --[[ Constants ]] -------------------------------------------------------------------------- local DEBUG = false local DEBUG_TELE = false - local UPDATE_PERIOD = 9 - local JITTER_RADIUS = 6 - local MAX_RADIUS = 1000 - local INC_RADIUS = BASE_RADIUS / 2 - local THREADS_PER_BATCH = 3 - local THREADS_PER_BATCH_HOOK = 5 + local UPDATE_PERIOD = 9 -- 9 seconds per tick + local JITTER_RADIUS = 1 -- random point within this radius + local MAX_RADIUS = 1000 -- cap the max radius + local INC_RADIUS = 3 -- increase this amount after we fail + local BASE_RADIUS = 15 -- don't spawn near player's base + 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 ]] @@ -33,13 +79,91 @@ return Class(function(self, inst) self.inst = inst --Private - local regrowth_table_populated_by_mod = false + local ready = false local regrowth_table = {} local entity_list = {} -------------------------------------------------------------------------- --[[ 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) if entity_list[ent.prefab] == nil then @@ -57,7 +181,7 @@ return Class(function(self, inst) ent:RemoveEventCallback("onremove", EntityDeathEventHandler, nil) 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 @@ -75,16 +199,16 @@ return Class(function(self, inst) local orig_tile = inst.Map:GetTileAtPoint(position.x, position.y, position.z) local status = TestRegrowth(x,y,z, prefab, orig_tile) - if status == REGROW_STATUS.STRUCT then + if CACHE_RETRY[status] ~= nil 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 return status end if status ~= REGROW_STATUS.SUCCESS 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 return status end @@ -95,7 +219,7 @@ return Class(function(self, inst) instance:ListenForEvent("onremove", EntityDeathEventHandler, nil) 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 if DEBUG_TELE then @@ -120,19 +244,22 @@ return Class(function(self, inst) end end if DEBUG then - print("[EventRegrowth] Hooked " .. count .. " " .. prefab) + print("[ExtraRegrowth] Hooked " .. count .. " " .. prefab) end end - local function HookAllEntities(ents) + local function HookAllRegisteredPrefabs() local count = 0 - local delay = 0 - for prefab in pairs(ents) do - inst:DoTaskInTime(delay, function() HookEntities(prefab) end) - count = count + 1 - if math.fmod(count, THREADS_PER_BATCH_HOOK) == 0 then - delay = delay + 1 + for guid,ent in pairs(Ents) do + if regrowth_table[ent.prefab] ~= nil then + ent:RemoveEventCallback("onremove", EntityDeathEventHandler, nil) + ent:ListenForEvent("onremove", EntityDeathEventHandler, nil) + count = count + 1 end + end + + if DEBUG then + print("[ExtraRegrowth] Hooked " .. count .. " entities") end end @@ -144,18 +271,23 @@ return Class(function(self, inst) end function self:FinishModConfig() - regrowth_table_populated_by_mod = true + HookAllRegisteredPrefabs() + ready = true end function self:RegisterRegrowth(prefab, product, interval) if interval == nil 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 interval = 480 end + if DEBUG then + interval = interval / 100 + end + if regrowth_table[prefab] == nil then -- avoid duplicate registration regrowth_table[prefab] = @@ -164,21 +296,19 @@ return Class(function(self, inst) interval = interval } - HookEntities(prefab) end 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 -------------------------------------------------------------------------- --[[ Initialization ]] -------------------------------------------------------------------------- - - inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate(UPDATE_PERIOD) end) - inst:ListenForEvent("ms_cyclecomplete", function() HookAllEntities(regrowth_table) end) -- every ~ 1 day we rehook every entities - inst:DoTaskInTime(0, function() HookAllEntities(regrowth_table) end) + inst:DoTaskInTime(0, function() HookAllRegisteredPrefabs() end) + inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate() end) + inst:ListenForEvent("ms_cyclecomplete", function() HookAllRegisteredPrefabs() end) -- every ~ 1 day we rehook every entities -------------------------------------------------------------------------- --[[ Update ]] @@ -195,21 +325,20 @@ return Class(function(self, inst) data.remove = true end - if success == REGROW_STATUS.STRUCT then - -- only increase radius when there are structures nearby + if CACHE_RETRY[success] == nil then + -- only increase radius when not cached data.retry = data.retry + 1 end end - function self:LongUpdate(dt) - if not regrowth_table_populated_by_mod then + function self:LongUpdate() + if not ready 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 for prefab in pairs(entity_list) do if entity_list[prefab] == nil or #entity_list[prefab] == 0 then -- only do meaningful work @@ -222,7 +351,7 @@ return Class(function(self, inst) if entity_list[prefab][i].remove then -- handle expired objects first 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 table.remove(entity_list[prefab], i) else @@ -235,19 +364,14 @@ return Class(function(self, inst) end 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 if entity_list[prefab][i].interval == 0 then -- different threads local data = entity_list[prefab][i] - inst:DoTaskInTime(delay, function() RegrowPrefabTask(prefab, data) 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 + RegrowPrefabTask(prefab, data) end end end @@ -283,7 +407,7 @@ return Class(function(self, inst) } end 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 @@ -309,7 +433,7 @@ return Class(function(self, inst) } end 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 diff --git a/src/scripts/components/natural_regrowth.lua b/src/scripts/components/natural_regrowth.lua deleted file mode 100644 index baa2f55..0000000 --- a/src/scripts/components/natural_regrowth.lua +++ /dev/null @@ -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) diff --git a/src/scripts/wrpp_util.lua b/src/scripts/wrpp_util.lua deleted file mode 100644 index c7d2b02..0000000 --- a/src/scripts/wrpp_util.lua +++ /dev/null @@ -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 \ No newline at end of file