Jump to content

Help for a trader-harvestable mod


Recommended Posts

Hi guys, i'm trying to create a new item that is trader , so it can accept only certain items, and then is harvestable, so it can "grow" items of that type.

 

I have a trader problem atm, here's the code :

inst:AddComponent("trader")inst.components.trader:SetAcceptTest(isMultiplicable)inst.components.trader.onaccept = startGrowthinst.components.trader.onrefuse = refused
-- Check if the item is in the list based on its namelocal function isMultiplicable(item)	name = item.prefab	for k,v in pairs(multiplicables) do		if v.debugName == name then			return v		end	end	return nilend
-- Define the list of items this object may acceptlocal function startGrowth(inst, item)    itemToProduce = item	if not itemToProduce == nil then	-- Set the harvester values	inst.components.harvestable:SetUp(v.elementName, v.numberCreated, v.timeToCreate, onharvest, nil)	-- Start to grow	inst.components.harvestable:StartGrowing()    endend
local multiplicables ={	cutgrass = {debugName="cutgrass", numberCreated=5, timeToCreate=10},	woodLog = {debugName="log", numberCreated=3, timeToCreate=10}}  

So The component trader uses the isMultiplicable function that check is the item is in the multiplicables list (by comparing the names). If yes, it uses the startGrowth function that set the item to grow and the other parameters using the multiplicables parameters.

 

After some time, the player can then harvest the object and get a number of resource of the same type that he used.

 

The onrefused just throw an error

 

I actually have a problem with the isMultiplicable function, I tried to give it cutgrass and it refused it. Would you know why this happened ?

Link to comment
Share on other sites

from scripts/components/trader.lua:

function Trader:CanAccept( item )
    return self.enabled and (not self.test or self.test(self.inst, item))
end

 

As you can see, the first parameter is the instance (the trader), the second variable is the item.

 

Can you show your "refused" function? If you haven't declared that, then it should be obvious why there's an error (Lua is actually more tolerant when it comes to null-values, but undeclared variables still cause problems like in Java)

 

(EDIT: Also, onaccept's second parameter is the giver, the third is the item.)

 

EDIT2: The "startGrow" function will cause an error too. I commented it as much as I could

 

local function startGrowth(inst, item) --fill in the giver (inst,guy,item)
    itemToProduce = item
    if not itemToProduce == nil then --any variable that's not nil or false is considered true, so you can remove both the "not" and the "== nil"
    -- Set the harvester values
    inst.components.harvestable:SetUp(v.elementName, v.numberCreated, v.timeToCreate, onharvest, nil) --where does "v" come from? This function doesn't know it (Lua is function-orientated, not object-orientated). You can define a variable in the instance when iterating though (inst.product = v) or use the keys (multiplicables[item.prefab])
    -- Start to grow
    inst.components.harvestable:StartGrowing()
    end
end

 

 

Link to comment
Share on other sites

local function refused()	inst.AnimState:PlayAnimation(inst.anims.hit)end

And the animation is not added, so it fail. I'm using ressources from an other mod that does not have animations yet so I can't really add an animation, and I need a way of seeing if it accept or not

 

So I need to create a isMultiplicable function that has the same parameters right ?

 

Link to comment
Share on other sites

okay I made the changes, I still have an error but going home now, so BRB in 2 hours

 

New code : 

-- Define the list of items this object may acceptlocal function startGrowth(inst, giver, item)    infos = nil	for k,v in pairs(inst.multiplicables) do		if v.debugName == name then			infos = v		end	end	if itemToProduce then	-- Set the harvester values	inst.components.harvestable:SetUp(infos.elementName, infos.numberCreated, infos.timeToCreate, onharvest, nil)	-- Start to grow	inst.components.harvestable:StartGrowing()    endend-- Check if the item is in the list based on its namelocal function isMultiplicable(inst, item)	name = item.prefab	for k,v in pairs(inst.multiplicables) do		if v.debugName == name then			return true		end	end	return falseendlocal function refused()	inst.AnimState:PlayAnimation(inst.anims.hit)endlocal function fn(Sim)	local inst = CreateEntity()	local trans = inst.entity:AddTransform()	local anim = inst.entity:AddAnimState()    inst.entity:AddSoundEmitter()	inst.entity:AddDynamicShadow()	inst.DynamicShadow:SetSize( 4, 3 )	local minimap = inst.entity:AddMiniMapEntity()	minimap:SetIcon( "w_pond.tex" )	    MakeObstaclePhysics(inst, .4)	anim:SetBank("w_pond")	anim:SetBuild("w_pond")	anim:PlayAnimation("bees_loop")    inst:AddTag("structure")    inst:AddTag("playerowned")    inst:AddComponent("inspectable")    inst.components.inspectable.getstatus = function(inst)		if inst.components.harvestable and inst.components.harvestable:CanBeHarvested() then			return "READY"		end	end    inst:AddComponent("harvestable")    -- inst.components.harvestable:SetUp(nil, nil, nil, onharvest, updatelevel)	inst:AddComponent("trader")    inst.components.trader:SetAcceptTest(isMultiplicable)    inst.components.trader.onaccept = startGrowth	inst.components.trader.onrefuse = refused    inst:AddComponent("lootdropper")    inst:AddComponent("workable")    inst.components.workable:SetWorkAction(ACTIONS.HAMMER)    inst.components.workable:SetWorkLeft(4)	inst.components.workable:SetOnFinishCallback(onhammered)		return instend

I got an error in the CanAccept function, so in isMultipliable I guess. I'll look into it.

 

Thanks a lot for your help !

Link to comment
Share on other sites

okay I made the changes, I still have an error but going home now, so BRB in 2 hours

 

New code : 

-snip-

I got an error in the CanAccept function, so in isMultipliable I guess. I'll look into it.

 

Thanks a lot for your help !

 

Now both "name" in the for loop and "itemtoproduce" in the if-statement are undeclared variable names. The former can be directly replaced by "item.prefab", the latter should be "infos".

Also, did you define "onharvest"? If so, make sure you declare that before the "startGrowth" function.

 

There's no such thing as "inst.anims.hit" in the code. You can either place the anim string directly or create a table with the strings (in the main function "fn").

Also, that function "refused" needs to get the "inst" parameter.

 

"onhammered" near the bottom should be declared too, for the case you're missing it.

 

 

I initially had the impression that you'd be experienced in Java, but you seem to have problems with declarations (which are a bit more annoying in Java than in Lua). Maybe it's just hasty work though :p

Link to comment
Share on other sites

yeah I was quite in a hurry, and as a java dev I can't stand the variables without types x)

 

i'll past the full code :

require "prefabutil"local assets ={	Asset("ANIM", "anim/w_pond.zip"),    Asset("ANIM", "anim/bee_box.zip"),}local multiplicables ={	cutgrass = {debugName="cutgrass", numberCreated=5, timeToCreate=10},	woodLog = {debugName="log", numberCreated=3, timeToCreate=10}} local function onhammered(inst, worker)	if inst:HasTag("fire") and inst.components.burnable then	inst.components.burnable:Extinguish()end	inst.SoundEmitter:KillSound("loop")	inst.components.lootdropper:DropLoot()	inst.SoundEmitter:PlaySound("dontstarve/common/destroy_wood")	inst:Remove()endlocal function onhit(inst, worker)	if not inst:HasTag("burnt") then	inst.AnimState:PlayAnimation(inst.anims.hit)	inst.AnimState:PushAnimation(inst.anims.idle, false)	endendlocal function setlevel(inst, level)    if not inst.anims then    inst.anims = {idle = level.idle, hit = level.hit}    else    inst.anims.idle = level.idle    inst.anims.hit = level.hitend    inst.AnimState:PlayAnimation(inst.anims.idle)endlocal function onbuilt(inst)	inst.AnimState:PlayAnimation("place")	inst.AnimState:PushAnimation("idle", false)end-- Define the list of items this object may acceptlocal function startGrowth(inst, giver, item)    infos = nil	for k,v in pairs(inst.multiplicables) do		if v.debugName == item.prefab then			infos = v		end	end	if infos then	-- Set the harvester values	inst.components.harvestable:SetUp(infos.elementName, infos.numberCreated, infos.timeToCreate, onharvest, nil)	-- Start to grow	inst.components.harvestable:StartGrowing()    endend-- Check if the item is in the list based on its namelocal function isMultiplicable(inst, item)	name = item.prefab	for k,v in pairs(inst.multiplicables) do		if v.debugName == name then			return true		end	end	return falseendlocal function refused()	inst.AnimState:PlayAnimation(inst.anims.hit)endlocal function fn(Sim)	local inst = CreateEntity()	local trans = inst.entity:AddTransform()	local anim = inst.entity:AddAnimState()    inst.entity:AddSoundEmitter()	inst.entity:AddDynamicShadow()	inst.DynamicShadow:SetSize( 4, 3 )	local minimap = inst.entity:AddMiniMapEntity()	minimap:SetIcon( "w_pond.tex" )	    MakeObstaclePhysics(inst, .4)	anim:SetBank("w_pond")	anim:SetBuild("w_pond")	anim:PlayAnimation("bees_loop")    inst:AddTag("structure")    inst:AddTag("playerowned")    inst:AddComponent("inspectable")    inst.components.inspectable.getstatus = function(inst)		if inst.components.harvestable and inst.components.harvestable:CanBeHarvested() then			return "READY"		end	end    inst:AddComponent("harvestable")    -- inst.components.harvestable:SetUp(nil, nil, nil, onharvest, updatelevel)	inst:AddComponent("trader")    inst.components.trader:SetAcceptTest(isMultiplicable)    inst.components.trader.onaccept = startGrowth	inst.components.trader.onrefuse = refused    inst:AddComponent("lootdropper")    inst:AddComponent("workable")    inst.components.workable:SetWorkAction(ACTIONS.HAMMER)    inst.components.workable:SetWorkLeft(4)	inst.components.workable:SetOnFinishCallback(onhammered)		return instendreturn Prefab("common/w_pond", fn, assets, prefabs),		   MakePlacer( "common/w_pond_placer", "w_pond", "w_pond", "bees_loop" ) 

Still the same error, just got home

 

EDIt : so no onHarvest method, since I don't have anything to do more than what the component does itself. Do I still need to create an empty function ?

Link to comment
Share on other sites

@pyrovoice, you are refering to "onharvest" when there is no variable called that. The component does not strictly request it, so you can leave it out (or replace with nil if you need to set the parameter after). It's that easy.

 

I see where the "inst.anims.hit" comes from now. You haven't really installed that system yet, so I suggest a placeholder of some kind. Consider "pushing" an idle animation afterwards (same as "PlayAnimation" but called "PushAnimation", so it plays after the current and previously queued ones).

 

On a side note, this looks like an interesting thing.

Link to comment
Share on other sites

fixed, I got an error, apparently 

local function startGrowth(inst, giver, item)    infos = nil	for k,v in pairs(inst.multiplicables) do		if v.debugName == item.prefab then			infos = v

inst.multiplicables does not return a table. I think there is an access problem since apparently it returned nil. Should I pass inst.components.trader:SetAcceptTest(isMultiplicable(this)) or something ?

 

And I think i'll focus on animations when the item work, so I can be happy inside :D

Link to comment
Share on other sites

fixed, I got an error, apparently 

local function startGrowth(inst, giver, item)    infos = nil	for k,v in pairs(inst.multiplicables) do		if v.debugName == item.prefab then			infos = v

inst.multiplicables does not return a table. I think there is an access problem since apparently it returned nil. Should I pass inst.components.trader:SetAcceptTest(isMultiplicable(this)) or something ?

 

And I think i'll focus on animations when the item work, so I can be happy inside :grin:

 

I totally missed that. It's a refernce problem.

 

Lua is not object-orientated, unlike Java. In Java, anything in a class belongs to that classs. In Lua, "ownership" needs to be explicit. You declared the table as "local", meaning it's a variable in this file/function/loop/whatever. Local variables only exist in the block they're created (until the next "end" or "return" is reached, if you will).

 

So, all you need to do is remove the "inst.". Or you declare the table in the main function "fn" as "inst.multiplicables". ...what BlueBerrys said.

 

 

Sorry if my wording is confusing, I am mostly self-learned. :wilson_nerdy:

 

 

And careful with things like "inst.components.trader:SetAcceptTest(isMultiplicable(this))". Using brackets fires a function, and unless they "return" something specific (e.g. return "bar", "foo") they return nil. If you, for some reason, need to pass a variable to that function, you can cheat a bit by making another function like so:

 

blabla:SetSomething(function(standardvariables) MyFunction(specialVariable, standardvariables, blah) end)

 

Link to comment
Share on other sites

Oh okay ! that has been fixed, and I also fixed the local infos in startGrowth

 

Now, the item accept cutgrass, make it grow and let us harvest it after 10 sec, but don't give anything on harvest.  This is supposed to be handled in harvestable component right ? Maybe I have to change

-- Set the harvester valuesinst.components.harvestable:SetUp(infos.elementName, infos.numberCreated, infos.timeToCreate, nil, nil)

edit : i think it was -- Set the harvester values

inst.components.harvestable:SetUp(infos.debugName, infos.numberCreated, infos.timeToCreate, nil, nil)
 
that was wrong, I fixed it and testing
 
EDIT2: YES ! it worked ! not the way I wanted it, but this is still nice x)
 
So, the problem with harvester is that you spawn 1 amount every X seconds, up to MAX (defined in the file). What I would like it to spawn X after the MAX time, not one by one. I need to see a bit more in the harvestable component
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...