Jump to content

Need help with PigKing script


_Q_
 Share

Recommended Posts

After making some changes to pigking.lua game crash after giving gold to pigking.Here is the code with changes:

local assets={	Asset("ANIM", "data/anim/pig_king.zip"),	Asset("SOUND", "data/sound/pig.fsb"),}local prefabs = {	"goldnugget",}[B] local function Rfun()    troll = math.random(1, 10)    if troll == 1 then       name = "\"goldnugget\""       elseif troll == 2 then           name = "\"twigs\""           elseif troll == 3 then             name = "\"cutgrass\""              else              name = "\"spoiledfood\""              end    return nameend[/B]local function OnGetItemFromPlayer(inst, giver, item)    if item.components.tradable.goldvalue > 0 then        inst.AnimState:PlayAnimation("cointoss")        inst.AnimState:PushAnimation("happy")        inst.AnimState:PushAnimation("idle", true)        inst:DoTaskInTime(20/30, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingThrowGold")                        for k = 1,item.components.tradable.goldvalue do               [B] local nug = SpawnPrefab(Rfun())[/B]                local pt = Vector3(inst.Transform:GetWorldPosition()) + Vector3(0,4.5,0)                                nug.Transform:SetPosition(pt:Get())                local down = TheCamera:GetDownVec()                local angle = math.atan2(down.z, down.x) + (math.random()*60-30)*DEGREES                --local angle = (-TUNING.CAM_ROT-90 + math.random()*60-30)/180*PI                local sp = math.random()*6+3                nug.Physics:SetVel(sp*math.cos(angle), math.random()*3+10, sp*math.sin(angle))            end        end)        inst:DoTaskInTime(1.5, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingHappy")        end)    endendlocal function OnRefuseItem(inst, giver, item)	inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingReject")    inst.AnimState:PlayAnimation("unimpressed")	inst.AnimState:PushAnimation("idle", true)endlocal function fn(Sim)    	local inst = CreateEntity()	local minimap = inst.entity:AddMiniMapEntity()	minimap:SetPriority( 5 )	--inst:AddComponent( "discoverable" )	--inst.components.discoverable:SetIcons( "treasure.png", "pigking.png" )	minimap:SetIcon( "pigking.png" )	minimap:SetPriority( 1 )	inst.entity:AddTransform()	inst.entity:AddAnimState()	inst.entity:AddSoundEmitter()	inst.entity:AddDynamicShadow()	inst.DynamicShadow:SetSize( 10, 5 )        MakeObstaclePhysics(inst, 2, .5)    --inst.Transform:SetScale(1.5,1.5,1.5)        inst.AnimState:SetBank("Pig_King")    inst.AnimState:PlayAnimation("idle", true)    inst.AnimState:SetBuild("Pig_King")        inst:AddComponent("inspectable")    inst:AddComponent("trader")	inst.components.trader:SetAcceptTest(		function(inst, item)			return item.components.tradable.goldvalue > 0		end)    inst.components.trader.onaccept = OnGetItemFromPlayer    inst.components.trader.onrefuse = OnRefuseItem	inst:ListenForEvent( "nighttime", function(global, data)          inst.components.trader:Disable()        inst.AnimState:PlayAnimation("sleep_pre")        inst.AnimState:PushAnimation("sleep_loop", true)        end, TheGlobalInstance)    	inst:ListenForEvent( "daytime", function(global, data)        inst.components.trader:Enable()        inst.AnimState:PlayAnimation("sleep_pst")        inst.AnimState:PushAnimation("idle", true)        end, TheGlobalInstance)        return instendreturn Prefab( "common/objects/pigking", fn, assets, prefabs)
The end result of my function is name of the prefab I want to spawn in quotes so I don't know why game crush after giving item to pigking. Any help would be great.Doing this other way also cause crush of game after giving meat to pigking:
local function OnGetItemFromPlayer(inst, giver, item)    if item.components.tradable.goldvalue > 0 then	troll = math.random(1, 10)        inst.AnimState:PlayAnimation("cointoss")        inst.AnimState:PushAnimation("happy")        inst.AnimState:PushAnimation("idle", true)        inst:DoTaskInTime(20/30, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingThrowGold")                        for k = 1,item.components.tradable.goldvalue do			    if troll == 1 then                local nug = SpawnPrefab("goldnugget")				else				local nug = SpawnPrefab("spoiledfood")				end                local pt = Vector3(inst.Transform:GetWorldPosition()) + Vector3(0,4.5,0)                                nug.Transform:SetPosition(pt:Get())                local down = TheCamera:GetDownVec()                local angle = math.atan2(down.z, down.x) + (math.random()*60-30)*DEGREES                --local angle = (-TUNING.CAM_ROT-90 + math.random()*60-30)/180*PI                local sp = math.random()*6+3                nug.Physics:SetVel(sp*math.cos(angle), math.random()*3+10, sp*math.sin(angle))            end        end)
Edited by _Q_
Link to comment
Share on other sites

Um....few things...

Make sure to check log.txt file in bin folder after crashes to see where and on what line the crash occured. Also you can use print("my text") statements in the code to test values. These show in the log file.

The prefab names should not be double quoted, just "name", not "\"name\""

Your variables in Rfun should have local in front of them to declare them at that level. Right now you are trying to set undeclared variables. Scope of variables in lua takes a bit of getting used to. For your variable setting to work as you have it means that you would declare them as local outside of the Rfun function (i.e. local to the pigman.lua code chunk)

Beyond that is the call to SpawnPrefab....because of how variables in lua works and pointers, etc you are passing the Rfun function itself instead of its return value which SpawnPrefab expects....I think there is a syntax to handle this but forget what it is atm.

The basic method is to create a temp variable to receive the return from Rfun and then pass that on to SpawnPrefab

see my changes here:

local function Rfun()    local troll = math.random(1, 10)    local name = "spoiledfood"    if troll == 1 then      name = "goldnugget"    elseif troll == 2 then      name = "twigs"    elseif troll == 3 then      name = "cutgrass"    end    return nameendlocal function OnGetItemFromPlayer(inst, giver, item)...            for k = 1,item.components.tradable.goldvalue do--[[ ORIGlocal nug = SpawnPrefab("goldnugget")-- /ORIG ]]-- MODlocal drop = Rfun()local nug = SpawnPrefab(drop)-- /MOD ]]                local pt = Vector3(inst.Transform:GetWorldPosition()) + Vector3(0,4.5,0)...
Edited by WrathOf
Link to comment
Share on other sites

By the way...the comment format I am using allows me to quickly activate and deactivate mod changes for testing etc.They are not necessary but I would highly recommend putting some sort of comments around your code changes to highlight (and remember later) what was changed. I like keeping the original code nearby too so I don't have to look it up from a backup."--[[" this means start a comment until you reach "]]" but keep in mind that you cannot nest them as in "--[[ outer --[[ inner comment ]] comment ]]" without using a different sytax.

Link to comment
Share on other sites

Then why the second method also cause crash, no function there, just if else.Was doing it your way and it also crashed.After printing this in lua: "\"spoiledfood\"" I got this: "spoiledfood"so it is exact thing like in default script

Edited by _Q_
Link to comment
Share on other sites

For the second method you tried....

Again this is because of the troll variable being undeclared, i.e. local troll = math.random(1, 10)

Also, I verified that the code I posted worked as you intented. Was amusing to get random drops.

EDIT:

this is what the log.txt file said about your code when I first tested it....

.../common/dont_starve/data/scripts/prefabs/pigking.lua:14: assign to undeclared variable 'troll'

Link to comment
Share on other sites

  • Developer

Hey _Q_,You'll need to add the items into the prefabs list. Also, "spoiledfood" is actually "spoiled_food". Here are the edits that I've tested to work:

local prefabs = {	"goldnugget",    "twigs",    "cutgrass",    "spoiled_food"}local function Rfun()    local troll = math.random(1, 10)    local name = "spoiled_food"    if troll == 1 then      name = "goldnugget"    elseif troll == 2 then      name = "twigs"    elseif troll == 3 then      name = "cutgrass"    end    return nameendlocal function OnGetItemFromPlayer(inst, giver, item)    if item.components.tradable.goldvalue > 0 then        inst.AnimState:PlayAnimation("cointoss")        inst.AnimState:PushAnimation("happy")        inst.AnimState:PushAnimation("idle", true)        inst:DoTaskInTime(20/30, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingThrowGold")                        for k = 1,item.components.tradable.goldvalue do                local nug = SpawnPrefab(Rfun())                local pt = Vector3(inst.Transform:GetWorldPosition()) + Vector3(0,4.5,0)                                nug.Transform:SetPosition(pt:Get())                local down = TheCamera:GetDownVec()                local angle = math.atan2(down.z, down.x) + (math.random()*60-30)*DEGREES                --local angle = (-TUNING.CAM_ROT-90 + math.random()*60-30)/180*PI                local sp = math.random()*6+3                nug.Physics:SetVel(sp*math.cos(angle), math.random()*3+10, sp*math.sin(angle))            end        end)        inst:DoTaskInTime(1.5, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingHappy")        end)    endend
Link to comment
Share on other sites

[MENTION=5551]_Q_[/MENTION]regarding the quotes text....a return from print ofspoiled_foodis not interpreted the same as a return of"spoiled_food"double quoting the text give this error:.../common/dont_starve/data/scripts/prefabs/pigking.lua:50: attempt to index local 'nug' (a nil value)since the prefab name is used as a lookup against a master list and SpawnPrefab could not find it. [MENTION=2]Bigfoot[/MENTION]I get an error when using SpawnPrefab(Rfun())? Will test again. Must of been the wrong prefab name :DAlso, regarding the prefab assets lists....I know we are *supposed* to add all used prefabs to this but I have come across instances in your code that do *not* do this and everything seems to work fine.I thought that was more about pre-loading the assets versus *required*?

Link to comment
Share on other sites

Lol @ trying to use forums as a chat app :D [MENTION=2]Bigfoot[/MENTION]Ok, so it is best practice to add used prefabs to the assets list but not *required*?Is there any issue with memory allocation or anything that we should be concered with if we do *not* add to the assets list?

Link to comment
Share on other sites

Hey _Q_,You'll need to add the items into the prefabs list. Also, "spoiledfood" is actually "spoiled_food". Here are the edits that I've tested to work:

local prefabs = {	"goldnugget",    "twigs",    "cutgrass",    "spoiled_food"}local function Rfun()    local troll = math.random(1, 10)    local name = "spoiled_food"    if troll == 1 then      name = "goldnugget"    elseif troll == 2 then      name = "twigs"    elseif troll == 3 then      name = "cutgrass"    end    return nameendlocal function OnGetItemFromPlayer(inst, giver, item)    if item.components.tradable.goldvalue > 0 then        inst.AnimState:PlayAnimation("cointoss")        inst.AnimState:PushAnimation("happy")        inst.AnimState:PushAnimation("idle", true)        inst:DoTaskInTime(20/30, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingThrowGold")                        for k = 1,item.components.tradable.goldvalue do                local nug = SpawnPrefab(Rfun())                local pt = Vector3(inst.Transform:GetWorldPosition()) + Vector3(0,4.5,0)                                nug.Transform:SetPosition(pt:Get())                local down = TheCamera:GetDownVec()                local angle = math.atan2(down.z, down.x) + (math.random()*60-30)*DEGREES                --local angle = (-TUNING.CAM_ROT-90 + math.random()*60-30)/180*PI                local sp = math.random()*6+3                nug.Physics:SetVel(sp*math.cos(angle), math.random()*3+10, sp*math.sin(angle))            end        end)        inst:DoTaskInTime(1.5, function()             inst.SoundEmitter:PlaySound("dontstarve/pig/PigKingHappy")        end)    endend
Thank You [MENTION=2]Bigfoot[/MENTION]Thank You @ WrathOfIt seems I need to find better lua tutorials, and pay more attention to prefab names.
Link to comment
Share on other sites

[MENTION=5551]_Q_[/MENTION]

I thought of something else....one of my best practices (or hard headed-ness :D)

Verify any possible values returned by a function so in this case the "nil" return is not being evaluated and could cause an unhandled exception if you will.

So to me the following is best:

local nug = SpawnPrefab(Rfun())

if not nug then print("Error: Unexpected 'nil' return from SpawnPrefab") return end

Link to comment
Share on other sites

  • Developer

[MENTION=10271]WrathOf[/MENTION] I had to speak to [MENTION=8]Kevin[/MENTION] about this.The prefab list is actually used as a build step to generate prefabs.xml. This is generated at compile time, not at run time, so adding prefabs to that list actually doesn't do anything. Basically it creates the dependencies to make sure the right prefabs are loaded prior to the game using them. If your game requires prefabs that have not yet been loaded, then you can explicitly call TheSim:LoadPrefabs() with a table that lists the prefabs you want to load. E.g. TheSim:LoadPrefabs({"twigs","spoiled_food"}). In this case all the items were already preloaded so we're good to go.Also I agree that crashing is a big part of making great mods :)

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...