Natural regrowth done.

This commit is contained in:
secXsQuared 2018-01-22 23:35:36 -05:00
parent 833c656be0
commit fda92dd393
5 changed files with 256 additions and 0 deletions

BIN
modicon.tex Normal file

Binary file not shown.

3
modicon.xml Normal file
View File

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

15
modinfo.lua Normal file
View File

@ -0,0 +1,15 @@
name = "World Regrowth Ex"
description = "Advanced world regrowth"
author = "lolo"
version = "0.0.1"
forumthread = ""
api_version = 10
icon_atlas = "modicon.xml"
icon = "modicon.tex"
all_clients_require_mod = false
client_only_mod = false
dst_compatible = true

26
modmain.lua Normal file
View File

@ -0,0 +1,26 @@
if GLOBAL.STRINGS.NAMES.MIGRATION_PORTAL then
AddPrefabPostInit("world", function(inst)
if inst.ismastersim then
inst:AddComponent("natural_regrowth")
end
end)
else
AddPrefabPostInit("forest", function(inst)
if inst.ismastersim then
inst:AddComponent("natural_regrowth")
end
end)
end
AddComponentPostInit("natural_regrowth", function(component)
component:RegisterRegrowth("grass", "grass")
end)
AddComponentPostInit("natural_regrowth", function(component)
component:RegisterRegrowth("evergreen", "evergreen")
end)
--"forest" for the overworld
--"cave" for the caves.
--No more "world" prefab.

View File

@ -0,0 +1,212 @@
--------------------------------------------------------------------------
--[[ NaturalRegrowth class definition ]]
-- A modified version of the original desolationspawner.lua
-- It acts as a standalone regrowth manager and is in dependent of the 3 existing ones
-- It's unlikely affected by game updates as long as Klei doesn't change the API (they shouldn't)
-- Klei has copyright over existing code used in this file.
-- by lolo Jan. 2018.
--------------------------------------------------------------------------
return Class(function(self, inst)
assert(TheWorld.ismastersim, "natrual_regrowth should not exist on client")
require "map/terrain"
--------------------------------------------------------------------------
--[[ Constants ]]
--------------------------------------------------------------------------
local RETRY_PER_PREFAB = 5 -- retry 5 times for each prefab
local DEBUG = true
local UPDATE_PERIOD = 31 -- less likely to update on the same frame as others
local BASE_RADIUS = 20
local EXCLUDE_RADIUS = 3
local MIN_PLAYER_DISTANCE = 64 * 1.2 -- this is our "outer" sleep radius
--------------------------------------------------------------------------
--[[ Member variables ]]
--------------------------------------------------------------------------
--Public
self.inst = inst
--Private
local regrowth_table = {}
local area_data = {}
--------------------------------------------------------------------------
--[[ Private member functions ]]
--------------------------------------------------------------------------
local function CanRegrow(x, y, z, prefab)
if IsAnyPlayerInRange(x,y,z, MIN_PLAYER_DISTANCE, nil) then
return false
end
local ents = TheSim:FindEntities(x,y,z, EXCLUDE_RADIUS)
if #ents > 0 then
-- Too dense
return false
end
local ents = TheSim:FindEntities(x,y,z, BASE_RADIUS, nil, nil, { "structure", "wall" })
if #ents > 0 then
-- Don't spawn inside bases
return false
end
if not (TheWorld.Map:CanPlantAtPoint(x, y, z) and
TheWorld.Map:CanPlacePrefabFilteredAtPoint(x, y, z, prefab))
or (RoadManager ~= nil and RoadManager:IsOnRoad(x, 0, z)) then
-- Not ground we can grow on
return false
end
return true
end
local function TryRegrowth(area, prefab, product)
if TheWorld.topology.nodes[area] == nil then
return false
end
local points_x, points_y = TheWorld.Map:GetRandomPointsForSite(TheWorld.topology.nodes[area].x, TheWorld.topology.nodes[area].y, TheWorld.topology.nodes[area].poly, 1)
if #points_x < 1 or #points_y < 1 then
return
end
local x = points_x[1]
local z = points_y[1]
if CanRegrow(x,0,z, product) then
local instance = SpawnPrefab(product)
if instance ~= nil then
instance.Transform:SetPosition(x,0,z)
end
if DEBUG then
print("[RegrowthEx] Spawned a ",product," for prefab ",prefab," at ", "(", x,0,z, ")", " in ", area)
c_teleport(x,0,z)
end
return true
else
return false
end
end
local function PopulateAreaData(prefab)
if TheWorld.generated == nil then
-- Still starting up, not ready yet.
return
end
for area, densities in pairs(TheWorld.generated.densities) do
if densities[prefab] ~= nil then
for id, v in ipairs(TheWorld.topology.ids) do
if v == area then
if area_data[prefab] == nil then
area_data[prefab] = {}
end
table.insert(area_data[prefab], id)
break
end
end
end
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:RegisterRegrowth(prefab, product)
if DEBUG then
print("Registered ", product, " for prefab " ,prefab )
end
regrowth_table[prefab] = product
PopulateAreaData(prefab)
end
--------------------------------------------------------------------------
--[[ Initialization ]]
--------------------------------------------------------------------------
inst:DoPeriodicTask(UPDATE_PERIOD, function() self:LongUpdate(UPDATE_PERIOD) end)
inst:DoTaskInTime(0, PopulateAllAreaData)
--------------------------------------------------------------------------
--[[ Update ]]
--------------------------------------------------------------------------
function self:LongUpdate(dt)
for prefab in pairs(area_data) do
if DEBUG then
print("[RegrowthEx] Regrowing ", prefab, "...")
end
local areas = area_data[prefab]
local rand = math.random(1, #areas)
local attempts = 0
while attempts < RETRY_PER_PREFAB do
local success = TryRegrowth(areas[rand], prefab, regrowth_table[prefab])
attempts = attempts + 1
if success then
print("[RegrowthEx] Succeeded after ", attempts, " attempts.")
break
end
end
if DEBUG and attempts == RETRY_PER_PREFAB then
print("[RegrowthEx] Failed after ", attempts, " attempts.")
end
end
end
--------------------------------------------------------------------------
--[[ Save/Load ]]
--------------------------------------------------------------------------
function self:OnSave()
local data = {
areas = {}
}
for prefab in pairs(area_data) do
data.areas[prefab] = {}
for area in pairs(area_data[prefab]) do
table.insert(data.areas[prefab], area)
end
end
return data
end
function self:OnLoad(data)
for prefab in pairs(data.areas) do
for area in pairs(data.areas) do
if area_data[prefab] == nil then
area_data[prefab] = {}
end
table.insert(area_data[prefab], area)
end
end
end
--------------------------------------------------------------------------
--[[ End ]]
--------------------------------------------------------------------------
end)