Jump to content

Recommended Posts

Hi,

I want to add food to the invalid_foods table of the birdcage, so the bird will refuse to eat it. I tried this :
 


AddPrefabPostInit("birdcage", function(inst)

table.insert(invalid_foods, "myfoodprefab")

end)

but i got this crash :


[00:01:04]: error calling PrefabPostInit: birdcage in mod SummerFloraFauna: 
[string "../mods/SummerFloraFauna/scripts/postinit.l..."]:49: bad argument #1 to 'insert' (table expected, got nil)
LUA ERROR stack traceback:
        =[C] in function 'insert'
        ../mods/SummerFloraFauna/scripts/postinit.lua(49,1)
        =(tail call) ?
        =[C] in function 'xpcall'
        scripts/mods.lua(154,1) in function 'mod'
        scripts/mainfunctions.lua(184,1)
        =[C] in function 'SpawnPrefab'
        scripts/mainfunctions.lua(220,1) in function 'SpawnPrefab'
        scripts/util.lua(24,1) in function 'DebugSpawn'
        scripts/consolecommands.lua(159,1) in function 'c_spawn'
        c_spawn("birdcage")(1,1) in main chunk
        =[C] in function 'pcall'
        scripts/mainfunctions.lua(1363,1)	

when i try to spawn a birdcage. So what i am doing wrong ?

Thanks for your help.

Well, the 'birdcage' is a local variable which you cannot modify directly in AddPrefabPostInit.

There are several ways to modify a local variable, like overriding the birdcage.lua by placing a modified version in script/prefabs folder in you mod folder, or you can override the ShouldAcceptItem function in birdcage. But I think this is a more elegant way:

Quote

 

AddPrefabPostInit("birdcage", function(inst)

    local i = 1
    
    while true do
        local n,v = GLOBAL.debug.getupvalue(v.components.trader.test, i)
        if n == "invalid_foods" then
            table.insert(v, "myfoodprefab")
            return
        -- When "invalid_foods" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find invalid_foods, something is wrong!")
            return
        end
        i = i + 1
    end

end)

 

 

Edited by ptr
remove lines which are not useful

Thanks i'll try it. Should i do something similar if i want to modify the DigestFood function to add more result to the thing i can obtain when feeding a bird ?
(It's the next step of what i want to do, ideally i would like that the bird will give a "monster egg" if you give it a monster food)

quite similar

Quote

 

AddPrefabPostInit("birdcage", function(inst)

    local i = 1
    
    while true do
        local n,v = GLOBAL.debug.getupvalue(v.components.trader.onaccept, i)
        if n == "DigestFood" then
            local oldDigestFood=v
            v = function(inst, giver, item)
                -- TODO:add your own code
                
                -- you can remove this if you don't need the original code
                oldDigestFood(inst, giver, item)
            end
            return
        -- When "DigestFood" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find DigestFood, something is wrong!")
            return
        end
        i = i + 1
    end

end)

 

 

I tried this :

AddPrefabPostInit("birdcage", function(inst)

    local i = 1
    
    while true do
        local n,v = GLOBAL.debug.getupvalue(v.components.trader.onaccept, i)
        if n == "DigestFood" then
            local oldDigestFood=v
            v = function(inst, food)
							  
					if food.components.edible.foodtype == FOODTYPE.MEAT and item.prefab:HasTag("monstermeat") then
						--If the food is meat:
							--Spawn an egg.
						inst.components.lootdropper:SpawnLootPrefab("cutgrass")
					elseif food.components.edible.foodtype == FOODTYPE.MEAT then
						inst.components.lootdropper:SpawnLootPrefab("bird_egg")
					else
						local seed_name = string.lower(food.prefab .. "_seeds")
						if Prefabs[seed_name] ~= nil then
							--If the food has a relavent seed type:
								--Spawn 1 or 2 of those seeds.
							local num_seeds = math.random(2)
							for k = 1, num_seeds do
								inst.components.lootdropper:SpawnLootPrefab(seed_name)
							end
								--Spawn regular seeds on a 50% chance.
							if math.random() < 0.5 then
								inst.components.lootdropper:SpawnLootPrefab("seeds")
							end
						else
							--Otherwise...
								--Spawn a poop 1/3 times.
							if math.random() < 0.33 then
								local loot = inst.components.lootdropper:SpawnLootPrefab("guano")
								loot.Transform:SetScale(.33, .33, .33)
							end
						end
					end
					
    local bird = GetBird(inst)
    if bird and bird:IsValid() and bird.components.perishable then
        bird.components.perishable:SetPercent(1)
    end
  -- TODO:add your own code
                
                -- you can remove this if you don't need the original code
                oldDigestFood(inst, food)
            end
            return
        -- When "DigestFood" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find DigestFood, something is wrong!")
            return
        end
        i = i + 1
    end

end) 

But got this :


[00:00:21]: error calling PrefabPostInit: birdcage in mod SummerFloraFauna: 
[string "../mods/SummerFloraFauna/scripts/postinit.l..."]:40: attempt to index global 'v' (a nil value)
LUA ERROR stack traceback:
        ../mods/SummerFloraFauna/scripts/postinit.lua(40,1)
        =(tail call) ?
        =[C] in function 'xpcall'
        scripts/mods.lua(154,1) in function 'mod'
        scripts/mainfunctions.lua(184,1)
        =[C] in function 'SpawnPrefab'
        scripts/mainfunctions.lua(220,1) in function 'SpawnPrefab'
        scripts/mainfunctions.lua(226,1) in function 'SpawnSaveRecord'
        scripts/gamelogic.lua(430,1) in function 'PopulateWorld'
        scripts/gamelogic.lua(680,1) in function 'DoInitGame'
        scripts/gamelogic.lua(798,1) in function 'cb'
	...
        =[C] in function 'GetPersistentString'
        scripts/saveindex.lua(250,1) in function 'Load'
        scripts/gamelogic.lua(982,1) in function 'callback'
        scripts/playerprofile.lua(853,1) in function 'Set'
        scripts/playerprofile.lua(714,1)
        =[C] in function 'GetPersistentString'
        scripts/playerprofile.lua(712,1) in function 'Load'
        scripts/gamelogic.lua(981,1) in main chunk
        =[C] in function 'require'
        scripts/mainfunctions.lua(836,1)	

 

(cutgrass is here only for testing purpose, i plan to change it later)

Edited by Lumina

I tried various things to see if the error was related to this, it's one of the change i made trying to see if i can fix it myself.

Now i have another crash :


AddPrefabPostInit("birdcage", function(inst)

    local i = 1
    
    while true do
        local n,v = GLOBAL.debug.getupvalue(inst.components.trader.onaccept, i)
        if n == "DigestFood" then
            local oldDigestFood=v
            v = function(inst, giver, item)
							  
					if food.components.edible.foodtype == FOODTYPE.MEAT and item.prefab:HasTag("monstermeat") then
						--If the food is meat:
							--Spawn an egg.
						inst.components.lootdropper:SpawnLootPrefab("cutgrass")
					elseif food.components.edible.foodtype == FOODTYPE.MEAT then
						inst.components.lootdropper:SpawnLootPrefab("bird_egg")
					else
						local seed_name = string.lower(food.prefab .. "_seeds")
						if Prefabs[seed_name] ~= nil then
							--If the food has a relavent seed type:
								--Spawn 1 or 2 of those seeds.
							local num_seeds = math.random(2)
							for k = 1, num_seeds do
								inst.components.lootdropper:SpawnLootPrefab(seed_name)
							end
								--Spawn regular seeds on a 50% chance.
							if math.random() < 0.5 then
								inst.components.lootdropper:SpawnLootPrefab("seeds")
							end
						else
							--Otherwise...
								--Spawn a poop 1/3 times.
							if math.random() < 0.33 then
								local loot = inst.components.lootdropper:SpawnLootPrefab("guano")
								loot.Transform:SetScale(.33, .33, .33)
							end
						end
					end
					
    local bird = GetBird(inst)
    if bird and bird:IsValid() and bird.components.perishable then
        bird.components.perishable:SetPercent(1)
    end
  -- TODO:add your own code
                
                -- you can remove this if you don't need the original code
                oldDigestFood(inst, giver, item)
            end
            return
        -- When "DigestFood" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find DigestFood, something is wrong!")
            return
        end
        i = i + 1
    end

end) 

With this crash :

 


[00:01:22]: error calling PrefabPostInit: birdcage in mod SummerFloraFauna: 
[string "../mods/SummerFloraFauna/scripts/postinit.l..."]:40: attempt to index field 'trader' (a nil value)
LUA ERROR stack traceback:
        ../mods/SummerFloraFauna/scripts/postinit.lua(40,1)
        =(tail call) ?
        =[C] in function 'xpcall'
        scripts/mods.lua(154,1) in function 'mod'
        scripts/mainfunctions.lua(184,1)	

But the birdcage has the trader component so i don't see why it's nil ?
Could it be because if the birdcage is empty the trader component is disabled, hence nil ? And only enabled when active ? Should i add somewhere a test and if yes, where ?

Edit :

        local n,v = GLOBAL.debug.getupvalue(inst.components.trader.onaccept, i)

this is line 40 in my code.

Edited by Lumina

So i have no crash but it's not working either. This is the code, with prints :

AddPrefabPostInit("birdcage", function(inst)

					print("function step 1")
if not GLOBAL.TheWorld.ismastersim then
	return inst
end
					print("function step 2")

    local i = 1
    
    while true do
					print("function step 3")
        local n,v = GLOBAL.debug.getupvalue(inst.components.trader.onaccept, i)
        if n == "DigestFood" then
            local oldDigestFood=v
					print("function step 4")
            v = function(inst, giver, item)
							  
					print("function step 5")
					-- if food.components.edible.foodtype == FOODTYPE.MEAT and food.prefab == "myprefab" then
						--If the food is meat:
							--Spawn an egg.
						-- inst.components.lootdropper:SpawnLootPrefab("cutgrass")
					if food.components.edible.foodtype == FOODTYPE.MEAT then
						inst.components.lootdropper:SpawnLootPrefab("cutgrass")
					else
						local seed_name = string.lower(food.prefab .. "_seeds")
						if Prefabs[seed_name] ~= nil then
							--If the food has a relavent seed type:
								--Spawn 1 or 2 of those seeds.
							local num_seeds = math.random(2)
							for k = 1, num_seeds do
								inst.components.lootdropper:SpawnLootPrefab(seed_name)
							end
								--Spawn regular seeds on a 50% chance.
							if math.random() < 0.5 then
								inst.components.lootdropper:SpawnLootPrefab("seeds")
							end
						else
							--Otherwise...
								--Spawn a poop 1/3 times.
							if math.random() < 0.33 then
								local loot = inst.components.lootdropper:SpawnLootPrefab("guano")
								loot.Transform:SetScale(.33, .33, .33)
							end
						end
					end
					
    local bird = GetBird(inst)
    if bird and bird:IsValid() and bird.components.perishable then
        bird.components.perishable:SetPercent(1)
    end
  -- TODO:add your own code
                
                -- you can remove this if you don't need the original code
                oldDigestFood(inst, giver, item)
            end
            return
        -- When "DigestFood" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find DigestFood, something is wrong!")
            return
        end
        i = i + 1
    end

end) 

And in log :


[00:00:28]: function step 1	
[00:00:29]: function step 2	
[00:00:29]: function step 3	
[00:00:29]: function step 3	
[00:00:29]: function step 4	

It seems that i can't reach step 5. When giving the bird a meat, i obtain egg, not cutgrass.

I think i don't have the skill to make this kind of script work, since i don't understand how the n, v are supposed to work (and why it's not working). Thanks again, for all your help and the time you spent helping me. I'm grateful :)

Sorry for not testing the code. I have made several mistakes. The following are the correct versions:

for "invalid_foods" table

Quote

 

AddPrefabPostInit("birdcage", function(inst)

    local i = 1
    
    while true do
        local n,v = GLOBAL.debug.getupvalue(inst.components.trader.test, i)
        if n == "invalid_foods" then
            table.insert(v, "yourprefab")
            GLOBAL.debug.setupvalue(inst.components.trader.test, i, v)
            return
        -- When "invalid_foods" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find invalid_foods, something is wrong!")
            return
        end
        i = i + 1
    end

end)

 

for "DigestFood" function

Quote

 

AddPrefabPostInit("birdcage", function(inst)
    if not GLOBAL.TheWorld.ismastersim then
        return
    end

    local i = 1
    
    while true do
        local n,v = GLOBAL.debug.getupvalue(inst.components.trader.onaccept, i)
        if n == "DigestFood" then
            local oldDigestFood=v
            v = function(inst, food)
            -- What's happening here: It seems you just want to override the monster meats, so let the original function do the rest.
                if string.find(food.prefab,"monster") then
                    inst.components.lootdropper:SpawnLootPrefab("cutgrass")
                    local bird = (inst.components.occupiable and inst.components.occupiable:GetOccupant()) or nil
                    if bird and bird:IsValid() and bird.components.perishable then
                        bird.components.perishable:SetPercent(1)
                    end
                else
                    oldDigestFood(inst, food)
                end
            end
            GLOBAL.debug.setupvalue(inst.components.trader.onaccept, i, v)
            return
        -- When "DigestFood" does not exist. Shouldn't get here unless the birdcage file has been modified.
        elseif not n then
            print("Can't find DigestFood, something is wrong!")
            return
        end
        i = i + 1
    end

end) 

 

 

Thanks a lot, all is working fine now, it's amazing. I just added the :

 if not GLOBAL.TheWorld.ismastersim then
        return
    end 

to the first code.

And really, mistakes aren't a problem. You helped me, you made me a code that i was totally unable to do alone (neither to fix), and spent time for me, i'm really grateful.

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
×
  • Create New...