Jump to content

Spawning a prefab at the beginning of the season ?


Recommended Posts

I have a new plant in one of my mod, working a little like flowers when picked (nothing left on ground). So i want this prefab to spawn to avoid it disappears over time.

Ideally i would like it to appears at the start of each autumn. If possible, i would like to have more prefab spawning if there is few prefab, and less if they are a lot, with a limit (like, no spawn if already 50 prefab).

Someone could help me to know how to do this ? Component, and after ?

 

Thanks.

Link to comment
Share on other sites

@ProfFarnsworth

Ok i tried to use your code, modified because if i understand well, you are spawning the grasshoper near grass, and i need to spawn my prefab in a specific ground. But with the change i made, it's not working.

 

HotbushSpawner = Class(function(self, inst)
    self.inst = inst
    self.has_spawned = false
    self.only_spawn_offscreen = true     
    --self.inst:WatchWorldState("iswinter", OnSeasonChange)
    --self.inst:WatchWorldState("issummer", OnSeasonChange)
    --self.inst:ListenForEvent("ms_setseason", OnSeasonChange, TheWorld)  
    --self.inst:ListenForEvent("seasonChange", OnSeasonChange)
    inst:WatchWorldState("season", OnSeasonChange)
    
    
end)



function OnSeasonChange(inst, season)
    --print("OnSeasonChange entered")
    --print("The season is currently"..season)
    inst.components.plant_spawner:OnSeasonChange(inst, season)
end

function HotbushSpawner:SpawnHotbush(season)
    --print("Spawning grasshopper")
    --local season = data.season
    --if season ~= SEASONS.winter then
    if TheWorld.state.issummer then
        for i=1, math.random(6, 12) do        
            if not self.has_spawned then
			local pt = GLOBAL.Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
			local tile = GLOBAL.TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)	
			local canspawn = tile ~= GLOBAL.GROUND.IMPASSABLE and tile ~= GLOBAL.GROUND.INVALID and tile ~= 255
			canspawn = canspawn and (tile == GLOBAL.GROUND.FUNGUSRED)
			if canspawn then
                    local cave_hot_bush = GLOBAL.SpawnPrefab("cave_hot_bush")
                    cave_hot_bush.Transform:SetPosition(pt:Get())
                    --print("grasshopper spawned")               
                end
            end
        end
    end
    self.has_spawned = true
end

-- function HotbushSpawner:FindSpawnLocation()
    -- print("Finding spawn location for Grasshopper...")
    -- local allvalidgrass = {}
    -- for guid, ent in pairs(Ents) do
        -- if ent.entity:IsValid() and ent.prefab == "grass" and (not self.only_spawn_offscreen or ent:IsAsleep()) then
            -- table.insert(allvalidgrass, ent)
        -- end
    -- end
    -- --print("Found "..(# allvalidgrass).." valid grass entities to spawn from")
    -- if next(allvalidgrass) == nil then
        -- return
    -- else
        -- local spawngrass = GetRandomItem(allvalidgrass)
        -- return Vector3(spawngrass.Transform:GetWorldPosition()) 
    -- end
-- end

function HotbushSpawner:OnSeasonChange(inst, season)
    print("Season change detected")
    --local season = data.season
    --if season == SEASONS.winter then
end

function HotbushSpawner:OnSave()
    if self.has_spawned then
        return{has_spawned = self.has_spawned}
    end
end

function HotbushSpawner:OnLoad(data)
    if data then
        self.has_spawned = data.has_spawned
    end
    self:SpawnHotbush()
end

return HotbushSpawner

 

Do you have any clues about what is wrong with my code ? I used some code found on this forum for the "spawn on ground" part but i don't know if i put it well. Thanks for any help you could give.

Link to comment
Share on other sites

not sure what this line is meant to be doing:

inst.components.plant_spawner:OnSeasonChange(inst, season)

but maybe try replacing it with:

--this
self:SpawnHotbush(season)


--or if it gives an error with 'self' then try
TheWorld.components.hotbushspawner:SpawnHotbush(season)

 

Link to comment
Share on other sites

    inst.components.grasshopperspawner:OnSeasonChange(inst, season)

The original line in the file was this one, the only one in lower case, so i was wondering it was the name of the file. (my file is plant_spawner for the moment). I'll try your lines as soon as possible to see if it's better, thank.

Link to comment
Share on other sites

So i changed the code as suggested (and renamed the file so it's more clear). It's still not working, but i guess it's better because i got an error with the GLOBAL variable, meaning that the code use a part it wasn't using before.

Updated code.

 

Spoiler

HotbushSpawner = Class(function(self, inst)
    self.inst = inst
    self.has_spawned = false
    self.only_spawn_offscreen = true     
    --self.inst:WatchWorldState("iswinter", OnSeasonChange)
    --self.inst:WatchWorldState("issummer", OnSeasonChange)
    --self.inst:ListenForEvent("ms_setseason", OnSeasonChange, TheWorld)  
    --self.inst:ListenForEvent("seasonChange", OnSeasonChange)
    inst:WatchWorldState("season", OnSeasonChange)
    
    
end)

 

function OnSeasonChange(inst, season)
    --print("OnSeasonChange entered")
    --print("The season is currently"..season)
    -- inst.components.plant_spawner:OnSeasonChange(inst, season)
    TheWorld.components.hotbushspawner:SpawnHotbush(season)
end

function HotbushSpawner:SpawnHotbush(season)
    --print("Spawning grasshopper")
    --local season = data.season
    --if season ~= SEASONS.winter then
    if TheWorld.state.issummer then
        for i=1, math.random(6, 12) do        
            if not self.has_spawned then
            local pt = Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
            local tile = TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)    
            local canspawn = tile ~= GROUND.IMPASSABLE and tile ~= GROUND.INVALID and tile ~= 255
            canspawn = canspawn and (tile == GROUND.SAVANNA)
            if canspawn then
                    local cave_hot_bush = SpawnPrefab("cave_hot_bush")
                    cave_hot_bush.Transform:SetPosition(pt:Get())
                    --print("grasshopper spawned")               
                end
            end
        end
    end
    self.has_spawned = true
end

-- function HotbushSpawner:FindSpawnLocation()
    -- print("Finding spawn location for Grasshopper...")
    -- local allvalidgrass = {}
    -- for guid, ent in pairs(Ents) do
        -- if ent.entity:IsValid() and ent.prefab == "grass" and (not self.only_spawn_offscreen or ent:IsAsleep()) then
            -- table.insert(allvalidgrass, ent)
        -- end
    -- end
    -- --print("Found "..(# allvalidgrass).." valid grass entities to spawn from")
    -- if next(allvalidgrass) == nil then
        -- return
    -- else
        -- local spawngrass = GetRandomItem(allvalidgrass)
        -- return Vector3(spawngrass.Transform:GetWorldPosition())
    -- end
-- end

function HotbushSpawner:OnSeasonChange(inst, season)
    print("Season change detected")
    --local season = data.season
    --if season == SEASONS.winter then
end

function HotbushSpawner:OnSave()
    if self.has_spawned then
        return{has_spawned = self.has_spawned}
    end
end

function HotbushSpawner:OnLoad(data)
    if data then
        self.has_spawned = data.has_spawned
    end
    self:SpawnHotbush()
end

return HotbushSpawner

 

So i guess it's this part that doesn't work :



function HotbushSpawner:SpawnHotbush(season)
    --print("Spawning grasshopper")
    --local season = data.season
    --if season ~= SEASONS.winter then
	if TheWorld.state.issummer then
        for i=1, math.random(6, 12) do        
            if not self.has_spawned then
			local pt = Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
			local tile = TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)	
			local canspawn = tile ~= GROUND.IMPASSABLE and tile ~= GROUND.INVALID and tile ~= 255
			canspawn = canspawn and (tile == GROUND.SAVANNA)
			if canspawn then
                    local cave_hot_bush = SpawnPrefab("cave_hot_bush")
                    cave_hot_bush.Transform:SetPosition(pt:Get())
                    --print("grasshopper spawned")               
                end
            end
        end
    end
    self.has_spawned = true
end

 

(I changed ground to savanna for the test, i wanted to be sure it's not the problem.)

Edited by Lumina
Link to comment
Share on other sites

try this maybe

HotbushSpawner = Class(function(self, inst)
    self.inst = inst
    self.has_spawned = false
    --self.only_spawn_offscreen = true     
    --self.inst:WatchWorldState("iswinter", OnSeasonChange)
    --self.inst:WatchWorldState("issummer", OnSeasonChange)
    --self.inst:ListenForEvent("ms_setseason", OnSeasonChange, TheWorld)  
    --self.inst:ListenForEvent("seasonChange", OnSeasonChange)
    self.inst:WatchWorldState("season", function(inst, season)
		self:OnSeasonChange(inst, season)
	end)
    
    
end)

function HotbushSpawner:OnSeasonChange(inst, season)
    print("Season changed to: " .. season)
	if season == "summer" and not self.has_spawned then
		self:SpawnHotbush(season)
	end
end

function HotbushSpawner:SpawnHotbush(season)
    --print("Spawning Hotbush")
    for i=1, math.random(6, 12) do        
		local pt = Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
		local tile = TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)    
		if tile == GROUND.SAVANNA then
			local cave_hot_bush = SpawnPrefab("cave_hot_bush")
			cave_hot_bush.Transform:SetPosition(pt:Get())
			--print("Hotbush spawned")               
         end
    end
    self.has_spawned = true
end

-- function HotbushSpawner:FindSpawnLocation()
    -- print("Finding spawn location for Grasshopper...")
    -- local allvalidgrass = {}
    -- for guid, ent in pairs(Ents) do
        -- if ent.entity:IsValid() and ent.prefab == "grass" and (not self.only_spawn_offscreen or ent:IsAsleep()) then
            -- table.insert(allvalidgrass, ent)
        -- end
    -- end
    -- --print("Found "..(# allvalidgrass).." valid grass entities to spawn from")
    -- if next(allvalidgrass) == nil then
        -- return
    -- else
        -- local spawngrass = GetRandomItem(allvalidgrass)
        -- return Vector3(spawngrass.Transform:GetWorldPosition())
    -- end
-- end

function HotbushSpawner:OnSave()
    if self.has_spawned then
        return{has_spawned = self.has_spawned}
    end
end

function HotbushSpawner:OnLoad(data)
    if data then
        self.has_spawned = data.has_spawned
    end
    self:SpawnHotbush()
end

return HotbushSpawner

Link to comment
Share on other sites

@Aquaterion

I tried this and it didn't work. So i changed different things trying to see if something could work. I got some spawns in this condition

I replaced :



function HotbushSpawner:OnSeasonChange(inst, season)
    print("Season changed to: " .. season)
	if season == "summer" and not self.has_spawned then
		self:SpawnHotbush(season)
	end
end

By



function HotbushSpawner:OnSeasonChange(inst, season)
    print("Season changed to: " .. season)
	if season == "summer" then
		self:SpawnHotbush(season)
	end
end

And then i got one spawn, with the prints :

[00:01:09]: Season changed to: summer    
[00:01:09]: Spawning Hotbush    
[00:01:09]: Hotbush spawned   

(I uncommented the print for my test, but never got the "Spawning Hotbush" with the original code (even with the print uncommented i mean))

So i don't understand why the "if season == "summer" and not self.has_spawned then" doesn't work (and i don't understand how it should work...), but since the "not self.has_spawned" should be a test i guess it's important, so removing it could cause trouble ?

Also, in my differents tests, i got only one bush spawning. So i suppose this line "for i=1, math.random(6, 12) do        " is here to tell "repeat multiple times", so why i have only one bush ?

(If i understand well, it should like something like this :

Season changed to: summer

Spawning Hotbush

Hotbush spawned

Hotbush spawned

Hotbush spawned

Hotbush spawned

Hotbush spawned

Hotbush spawned

 

?)

 

Thanks a lot for all your help anyway, all of you, i'm really grateful :)

 

 

Edited by Lumina
Link to comment
Share on other sites

the for loop should TRY to spawn 6 to 12 bushes, but if it fails to spawn some, such as trying to spawn it anywhere else that isn't savanna, then that still would count as 1 TRY.

you could use a while loop like so:

function HotbushSpawner:SpawnHotbush(season)
    --print("Spawning Hotbush")
	local currentbushes = 0
	local maxbushes = math.random(6, 12)
	while currentbushes <= maxbushes do
		local pt = Vector3(math.random(-1000, 1000), 0, math.random(-1000, 1000))
		local tile = TheWorld.Map:GetTileAtPoint(pt.x, pt.y, pt.z)    
		if tile == GROUND.SAVANNA then
			local cave_hot_bush = SpawnPrefab("cave_hot_bush")
			cave_hot_bush.Transform:SetPosition(pt:Get())
			--print("Hotbush spawned")
			currentbushes = currentbushes + 1
        end
	end

    self.has_spawned = true
end

 

Link to comment
Share on other sites

Thanks, it seems to work fine :)

What is the risk if i let the "not self.has_spawned" removed of the test


function HotbushSpawner:OnSeasonChange(inst, season)
    print("Season changed to: " .. season)
	if season == "summer" then
		self:SpawnHotbush(season)
	end
end

?
Do i have a risk to have too much spawn, for example each time the server will start in summer or something ? Or is it fine to let it this way ?

Thanks :)

Link to comment
Share on other sites

17 hours ago, Lumina said:

Perfect, thanks again :)

Glad you got this sorted. Apologies haven't been around much. If memory serves "self.has_spawned" is a local variable so you should be fine without it. And @Aquaterion is right about the limit function. I don't care if some don't spawn as the grasshoppers reproduce so the while function should work for you since you are not killing them off.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...