ITSRAW Posted January 12, 2017 Share Posted January 12, 2017 (edited) Hello you wonderful community! I've been modding a character for DST the past week now. I've so far done custom speech, stats, etc. However, there has been one small problem.... As soon as the player starts, I wanted to give them a Crock Pot to start with. (You can probably guess who this mod is for). I do know the possibilties and the know-how to give a character a starting item, just not one for an item that can't be kept in the inventory in the first place. Or maybe my scripting isn't as good as I thought! local MakePlayerCharacter = require "prefabs/player_common" local assets = { Asset("SCRIPT", "scripts/prefabs/player_common.lua"), } local prefabs = {} -- Custom starting items local start_inv = { "spear" } -- When the character is revived from human local function onbecamehuman(inst) -- Set speed when reviving from ghost (optional) inst.components.locomotor:SetExternalSpeedMultiplier(inst, "gordonramsay_speed_mod", 1) end local function onbecameghost(inst) -- Remove speed modifier when becoming a ghost inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "gordonramsay_speed_mod") end -- When loading or spawning the character local function onload(inst) inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman) inst:ListenForEvent("ms_becameghost", onbecameghost) if inst:HasTag("playerghost") then onbecameghost(inst) else onbecamehuman(inst) end end -- This initializes for both the server and client. Tags can be added here. local common_postinit = function(inst) -- Minimap icon inst.MiniMapEntity:SetIcon( "gordonramsay.tex" ) end -- This initializes for the server only. Components are added here. local master_postinit = function(inst) -- choose which sounds this character will play inst.soundsname = "wilson" -- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used --inst.talker_path_override = "dontstarve_DLC001/characters/" -- Stats inst.components.health:SetMaxHealth(225) inst.components.hunger:SetMax(200) inst.components.sanity:SetMax(150) -- Damage multiplier (optional) inst.components.combat.damagemultiplier = 1 -- Hunger rate (optional) inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE inst.OnLoad = onload inst.OnNewSpawn = onload end return MakePlayerCharacter("gordonramsay", prefabs, assets, common_postinit, master_postinit, start_inv) Any kind soul out there willing to help? Thank you in advance! Edited January 12, 2017 by ITSRAW Link to comment Share on other sites More sharing options...
Lumina Posted January 12, 2017 Share Posted January 12, 2017 (edited) As far as i know, crockpot can't be given this way because it's not an item, it's a structure. I know it's possible to start with a structure "unlocked" and maybe ready to be deployed... I'll try to see if i find a topic about it because i don't remember how to do it. But if i don't find it and if you don't have any answer, i have an ugly way to do it : give the crockpot blueprint and the crockpot material as starting item. I hope someone will give a better solution. Edit You should find some answer about how to have a recipe unlocked (so crockpot here), but it will not "give" the crockpot, just the ability to build it. I think the code still work. I don't find the other code... Edited January 12, 2017 by Lumina Link to comment Share on other sites More sharing options...
ITSRAW Posted January 12, 2017 Author Share Posted January 12, 2017 (edited) 28 minutes ago, Lumina said: As far as i know, crockpot can't be given this way because it's not an item, it's a structure. I know it's possible to start with a structure "unlocked" and maybe ready to be deployed... I'll try to see if i find a topic about it because i don't remember how to do it. But if i don't find it and if you don't have any answer, i have an ugly way to do it : give the crockpot blueprint and the crockpot material as starting item. I hope someone will give a better solution. Yeah, that is what I thought as well. Never really could hold a structure in my inventory before either. (Except for the walls) I appreciate your help and willing to give me a hand! I'll keep look along side you. If nothing can be done about it, I think that suggestion you gave about the blueprint will work just as nicely as well. Once again, thank you, as I appreciate it very much. :] Edit for your edit: Appreciate it! That could work, I'll take a look into it. Hopefully someone can come along as think of a script for this kind of thing though. Otherwise, will just need to use that workaround! Edited January 12, 2017 by ITSRAW Link to comment Share on other sites More sharing options...
PanAzej Posted January 13, 2017 Share Posted January 13, 2017 (edited) This thing here took me 3 hours to get it right, enjoy: local ACTIONS = GLOBAL.ACTIONS local ActionHandler = GLOBAL.ActionHandler local SpawnPrefab = GLOBAL.SpawnPrefab function MovableCrockpotPostInit(inst) if GLOBAL.TheWorld.ismastersim then local function ondeploy(inst, pt) local cookpot = SpawnPrefab("cookpot") if cookpot ~= nil then cookpot.Transform:SetPosition(pt:Get()) cookpot.SoundEmitter:PlaySound("dontstarve/common/cook_pot_craft") inst:Remove() end end if not inst.components.deployable then inst:AddComponent("deployable") end inst.components.deployable.ondeploy = ondeploy if not inst.components.inventoryitem then inst:AddComponent("inventoryitem") end inst.components.inventoryitem.canbepickedup = false inst:AddTag("crockpot_regular") inst:ListenForEvent("onputininventory", function() if inst.components.container then if inst.components.container:IsOpen() then inst.components.container:Close() end inst.components.container.canbeopened = false end end) inst:ListenForEvent("gotnewitem", function() if inst.components.container and inst.components.container.canbeopened == true then inst.components.container:Open() end end) end end AddPrefabPostInit("cookpot", MovableCrockpotPostInit) -- Make a special action to pick up Crockpot only by a special character with rmb local CROCKPOTPICKUP = GLOBAL.Action({ priority=10 }) CROCKPOTPICKUP.str = "Pick up" CROCKPOTPICKUP.id = "CROCKPOTPICKUP" CROCKPOTPICKUP.fn = function(act) if act.doer.components.inventory ~= nil and act.target ~= nil and act.target.components.inventoryitem ~= nil and act.target.prefab == "cookpot" and not act.target:HasTag("burnt") and (act.target.components.container and not act.target.components.container:IsOpen() and act.target.components.container:IsEmpty()) and act.target.components.stewer and act.target.components.stewer.product == nil and not act.target.components.stewer:IsCooking() then act.doer:PushEvent("onpickupitem", { item = act.target }) act.doer.components.inventory:GiveItem(act.target, nil, act.target:GetPosition()) return true elseif act.target:HasTag("burnt") then return false, "ISBURNT" elseif not act.target:HasTag("burnt") and act.target.components.container and not act.target.components.container:IsEmpty() and act.target.components.stewer and not act.target.components.stewer:IsCooking() then return false, "ISFULL" elseif not act.target:HasTag("burnt") and (act.target.components.container and not act.target.components.container:IsEmpty() or act.target.components.stewer and act.target.components.stewer.product ~= nil or act.target.components.container and act.target.components.container:IsOpen()) then return false, "ISCOOKING" end end AddAction(CROCKPOTPICKUP) AddComponentAction("SCENE", "inventoryitem", function(inst, doer, actions, right) if right and doer.replica.inventory ~= nil and doer:HasTag("crockpot_pickuper") and inst:HasTag("crockpot_regular") and not inst:HasTag("fire") then table.insert(actions, ACTIONS.CROCKPOTPICKUP) end end) AddStategraphActionHandler("wilson_client", crockpotpickup_handler) local placecrockpot_handler = ActionHandler(ACTIONS.CROCKPOTPICKUP, function(inst) return "doshortaction" end) AddStategraphActionHandler("wilson", placecrockpot_handler) local placecrockpot_handler_client = ActionHandler(ACTIONS.CROCKPOTPICKUP, "doshortaction") AddStategraphActionHandler("wilson_client", placecrockpot_handler_client) GLOBAL.STRINGS.CHARACTERS.GENERIC.ACTIONFAIL.CROCKPOTPICKUP = { ISBURNT = "I can't pick it up, it's all burnt up.", ISCOOKING = "I can't pick it up, it's being used!", ISFULL = "I should empty it before picking it up!", } -- Regular "dropping" the item from inventory causes really troublesome bugs, so here we go with a custom action: local PLACECROCKPOT = GLOBAL.Action({ priority= 10, distance= 1.1}) PLACECROCKPOT.str = "Plant" PLACECROCKPOT.id = "PLACECROCKPOT" PLACECROCKPOT.fn = function(act) if act.invobject and act.invobject.components.deployable and act.invobject.components.deployable:CanDeploy(act.pos) then if act.invobject then if act.invobject.components.deployable:Deploy(act.pos, act.doer, act.rotation) then return true else act.doer.components.inventory:GiveItem(act.invobject) end end end end AddAction(PLACECROCKPOT) AddComponentAction("POINT", "deployable", function(inst, doer, pos, actions, right) if not right and doer and inst and inst:HasTag("crockpot_regular") and inst.replica and inst.replica.inventoryitem and inst.replica.inventoryitem:IsHeldBy(doer) then table.insert(actions, ACTIONS.PLACECROCKPOT) end end) AddStategraphActionHandler("wilson_client", placecrockpot_handler) local placecrockpot_handler = ActionHandler(ACTIONS.PLACECROCKPOT, function(inst) return "doshortaction" end) AddStategraphActionHandler("wilson", placecrockpot_handler) local placecrockpot_handler_client = ActionHandler(ACTIONS.PLACECROCKPOT, "doshortaction") AddStategraphActionHandler("wilson_client", placecrockpot_handler_client) Put this in your modmain. And add a "crockpot_pickuper" tag to your character. Edited January 13, 2017 by PanAzej there may still be some bugs here though, but I'll leave fixing them to you Link to comment Share on other sites More sharing options...
ITSRAW Posted January 13, 2017 Author Share Posted January 13, 2017 (edited) @PanAzej Oh. my. god. You're a HERO and lifesaver! You taking that much time out of your day for a random use like me. I am truly grateful and will not disappoint you! From the bottom of my heart, THANK YOU! If only there were an option to like a post more than once.... Only question is this. How exactly would I add a 'tag' to my character? Sorry to be more of a problem, but not really a pro at this modding yet. x) Edited January 13, 2017 by ITSRAW Link to comment Share on other sites More sharing options...
PanAzej Posted January 13, 2017 Share Posted January 13, 2017 2 hours ago, ITSRAW said: I am truly grateful and will not disappoint you! From the bottom of my heart, THANK YOU! No problem! 2 hours ago, ITSRAW said: Only question is this. How exactly would I add a 'tag' to my character? Sorry to be more of a problem, but not really a pro at this modding yet. x) Add this in your common_postinit function: inst:AddTag("crockpot_pickuper") The "picking up crockpot" action is exclusive to characters with this tag. Link to comment Share on other sites More sharing options...
Lumina Posted January 13, 2017 Share Posted January 13, 2017 I'm so happy when i see people like you providing amazing code like this ! Link to comment Share on other sites More sharing options...
PanAzej Posted January 13, 2017 Share Posted January 13, 2017 (edited) 1 hour ago, Lumina said: I'm so happy when i see people like you providing amazing code like this ! Thank you! "gotnewitem" eventlistener is broken, though. I mean, it doesn't do anything. The major bug with this code is that the Crockpot won't automatically open when you put items in it anymore. It could be fixed with yet another action, I think. Also, mobs like frogs can drop the Crockpot from the inventory, causing it to collide with character and in the end 'hover' in the air. That could also be fixed with workarounds. Probably removing colliders while putting it in inventory would work. But yeah, it's mostly working. Edited January 13, 2017 by PanAzej yes Link to comment Share on other sites More sharing options...
ITSRAW Posted January 13, 2017 Author Share Posted January 13, 2017 (edited) @PanAzej Found it! Thank you! How I know I found it, is that it sadly gave an error to me when I booted up the server. :/ Error message I get is: :39: ')' expected near 'inst' I've even tried adding that, but I get the same error message, but instead says ')' expected near ':' I attached an image to make it easier. Here is my character lua: local MakePlayerCharacter = require "prefabs/player_common" local assets = { Asset("SCRIPT", "scripts/prefabs/player_common.lua"), } local prefabs = {} -- Custom starting items local start_inv = { "spear" } -- When the character is revived from human local function onbecamehuman(inst) -- Set speed when reviving from ghost (optional) inst.components.locomotor:SetExternalSpeedMultiplier(inst, "gordonramsay_speed_mod", 1) end local function onbecameghost(inst) -- Remove speed modifier when becoming a ghost inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "gordonramsay_speed_mod") end -- When loading or spawning the character local function onload(inst) inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman) inst:ListenForEvent("ms_becameghost", onbecameghost) if inst:HasTag("playerghost") then onbecameghost(inst) else onbecamehuman(inst) end end -- This initializes for both the server and client. Tags can be added here. local common_postinit = function inst:AddTag("crockpot_pickuper") -- Minimap icon inst.MiniMapEntity:SetIcon( "gordonramsay.tex" ) end -- This initializes for the server only. Components are added here. local master_postinit = function(inst) -- choose which sounds this character will play inst.soundsname = "wilson" -- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used --inst.talker_path_override = "dontstarve_DLC001/characters/" -- Stats inst.components.health:SetMaxHealth(225) inst.components.hunger:SetMax(200) inst.components.sanity:SetMax(150) -- Damage multiplier (optional) inst.components.combat.damagemultiplier = 1 -- Hunger rate (optional) inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE inst.OnLoad = onload inst.OnNewSpawn = onload end return MakePlayerCharacter("gordonramsay", prefabs, assets, common_postinit, master_postinit, start_inv) And my modmain lua: PrefabFiles = { "gordonramsay", "gordonramsay_none", } local ACTIONS = GLOBAL.ACTIONS local ActionHandler = GLOBAL.ActionHandler local SpawnPrefab = GLOBAL.SpawnPrefab function MovableCrockpotPostInit(inst) if GLOBAL.TheWorld.ismastersim then local function ondeploy(inst, pt) local cookpot = SpawnPrefab("cookpot") if cookpot ~= nil then cookpot.Transform:SetPosition(pt:Get()) cookpot.SoundEmitter:PlaySound("dontstarve/common/cook_pot_craft") inst:Remove() end end if not inst.components.deployable then inst:AddComponent("deployable") end inst.components.deployable.ondeploy = ondeploy if not inst.components.inventoryitem then inst:AddComponent("inventoryitem") end inst.components.inventoryitem.canbepickedup = false inst:AddTag("crockpot_regular") inst:ListenForEvent("onputininventory", function() if inst.components.container then if inst.components.container:IsOpen() then inst.components.container:Close() end inst.components.container.canbeopened = false end end) inst:ListenForEvent("gotnewitem", function() if inst.components.container and inst.components.container.canbeopened == true then inst.components.container:Open() end end) end end AddPrefabPostInit("cookpot", MovableCrockpotPostInit) -- Make a special action to pick up Crockpot only by a special character with rmb local CROCKPOTPICKUP = GLOBAL.Action({ priority=10 }) CROCKPOTPICKUP.str = "Pick up" CROCKPOTPICKUP.id = "CROCKPOTPICKUP" CROCKPOTPICKUP.fn = function(act) if act.doer.components.inventory ~= nil and act.target ~= nil and act.target.components.inventoryitem ~= nil and act.target.prefab == "cookpot" and not act.target:HasTag("burnt") and (act.target.components.container and not act.target.components.container:IsOpen() and act.target.components.container:IsEmpty()) and act.target.components.stewer and act.target.components.stewer.product == nil and not act.target.components.stewer:IsCooking() then act.doer:PushEvent("onpickupitem", { item = act.target }) act.doer.components.inventory:GiveItem(act.target, nil, act.target:GetPosition()) return true elseif act.target:HasTag("burnt") then return false, "ISBURNT" elseif not act.target:HasTag("burnt") and act.target.components.container and not act.target.components.container:IsEmpty() and act.target.components.stewer and not act.target.components.stewer:IsCooking() then return false, "ISFULL" elseif not act.target:HasTag("burnt") and (act.target.components.container and not act.target.components.container:IsEmpty() or act.target.components.stewer and act.target.components.stewer.product ~= nil or act.target.components.container and act.target.components.container:IsOpen()) then return false, "ISCOOKING" end end AddAction(CROCKPOTPICKUP) AddComponentAction("SCENE", "inventoryitem", function(inst, doer, actions, right) if right and doer.replica.inventory ~= nil and doer:HasTag("crockpot_pickuper") and inst:HasTag("crockpot_regular") and not inst:HasTag("fire") then table.insert(actions, ACTIONS.CROCKPOTPICKUP) end end) AddStategraphActionHandler("wilson_client", crockpotpickup_handler) local placecrockpot_handler = ActionHandler(ACTIONS.CROCKPOTPICKUP, function(inst) return "doshortaction" end) AddStategraphActionHandler("wilson", placecrockpot_handler) local placecrockpot_handler_client = ActionHandler(ACTIONS.CROCKPOTPICKUP, "doshortaction") AddStategraphActionHandler("wilson_client", placecrockpot_handler_client) GLOBAL.STRINGS.CHARACTERS.GENERIC.ACTIONFAIL.CROCKPOTPICKUP = { ISBURNT = "I can't pick it up, it's all burnt up.", ISCOOKING = "I can't pick it up, it's being used!", ISFULL = "I should empty it before picking it up!", } -- Regular "dropping" the item from inventory causes really troublesome bugs, so here we go with a custom action: local PLACECROCKPOT = GLOBAL.Action({ priority= 10, distance= 1.1}) PLACECROCKPOT.str = "Plant" PLACECROCKPOT.id = "PLACECROCKPOT" PLACECROCKPOT.fn = function(act) if act.invobject and act.invobject.components.deployable and act.invobject.components.deployable:CanDeploy(act.pos) then if act.invobject then if act.invobject.components.deployable:Deploy(act.pos, act.doer, act.rotation) then return true else act.doer.components.inventory:GiveItem(act.invobject) end end end end AddAction(PLACECROCKPOT) AddComponentAction("POINT", "deployable", function(inst, doer, pos, actions, right) if not right and doer and inst and inst:HasTag("crockpot_regular") and inst.replica and inst.replica.inventoryitem and inst.replica.inventoryitem:IsHeldBy(doer) then table.insert(actions, ACTIONS.PLACECROCKPOT) end end) AddStategraphActionHandler("wilson_client", placecrockpot_handler) local placecrockpot_handler = ActionHandler(ACTIONS.PLACECROCKPOT, function(inst) return "doshortaction" end) AddStategraphActionHandler("wilson", placecrockpot_handler) local placecrockpot_handler_client = ActionHandler(ACTIONS.PLACECROCKPOT, "doshortaction") AddStategraphActionHandler("wilson_client", placecrockpot_handler_client) local starting_inv = { "spear", } Assets = { Asset( "IMAGE", "images/saveslot_portraits/gordonramsay.tex" ), Asset( "ATLAS", "images/saveslot_portraits/gordonramsay.xml" ), Asset( "IMAGE", "images/selectscreen_portraits/gordonramsay.tex" ), Asset( "ATLAS", "images/selectscreen_portraits/gordonramsay.xml" ), Asset( "IMAGE", "images/selectscreen_portraits/gordonramsay_silho.tex" ), Asset( "ATLAS", "images/selectscreen_portraits/gordonramsay_silho.xml" ), Asset( "IMAGE", "bigportraits/gordonramsay.tex" ), Asset( "ATLAS", "bigportraits/gordonramsay.xml" ), Asset( "IMAGE", "images/map_icons/gordonramsay.tex" ), Asset( "ATLAS", "images/map_icons/gordonramsay.xml" ), Asset( "IMAGE", "images/avatars/avatar_gordonramsay.tex" ), Asset( "ATLAS", "images/avatars/avatar_gordonramsay.xml" ), Asset( "IMAGE", "images/avatars/avatar_ghost_gordonramsay.tex" ), Asset( "ATLAS", "images/avatars/avatar_ghost_gordonramsay.xml" ), Asset( "IMAGE", "images/avatars/self_inspect_gordonramsay.tex" ), Asset( "ATLAS", "images/avatars/self_inspect_gordonramsay.xml" ), Asset( "IMAGE", "images/names_gordonramsay.tex" ), Asset( "ATLAS", "images/names_gordonramsay.xml" ), Asset( "IMAGE", "bigportraits/gordonramsay_none.tex" ), Asset( "ATLAS", "bigportraits/gordonramsay_none.xml" ), } local require = GLOBAL.require local STRINGS = GLOBAL.STRINGS -- The character select screen lines STRINGS.CHARACTER_TITLES.gordonramsay = "The Chef" STRINGS.CHARACTER_NAMES.gordonramsay = "Esc" STRINGS.CHARACTER_DESCRIPTIONS.gordonramsay = "*Is an extremely picky eater\n*Starts with crock pot and gains extra effects\n*Is very tough" STRINGS.CHARACTER_QUOTES.gordonramsay = "\"IT'S RAWWWWW\"" -- Custom speech strings STRINGS.CHARACTERS.GORDONRAMSAY = require "speech_gordonramsay" -- The character's name as appears in-game STRINGS.NAMES.gordonramsay = "Esc" AddMinimapAtlas("images/map_icons/gordonramsay.xml") -- Add mod character to mod character list. Also specify a gender. Possible genders are MALE, FEMALE, ROBOT, NEUTRAL, and PLURAL. AddModCharacter("gordonramsay", "MALE") I appreciate the help! Edited January 13, 2017 by ITSRAW Link to comment Share on other sites More sharing options...
PanAzej Posted January 13, 2017 Share Posted January 13, 2017 -- This initializes for both the server and client. Tags can be added here. local common_postinit = function(inst) -- Minimap icon inst.MiniMapEntity:SetIcon( "gordonramsay.tex" ) -- Tags inst:AddTag("crockpot_pickuper") end Link to comment Share on other sites More sharing options...
ITSRAW Posted January 13, 2017 Author Share Posted January 13, 2017 Awesome, thank you! No error messages here. Atm no crock pot is spawning when I spawn in the world, but that can be just something in the script possibly not working. So far it seems I've done everything right(thanks to you) but do you have any ideas for a fix? Not rushing or anything, just don't want this marvelous script to got to waste. Link to comment Share on other sites More sharing options...
PanAzej Posted January 13, 2017 Share Posted January 13, 2017 Oh. To have a Crockpot as a starting item do this: -- Custom starting items local start_inv = { "spear", "cookpot", } Since the Crockpot is now an inventory item, you can spawn with it properly. Link to comment Share on other sites More sharing options...
ITSRAW Posted January 14, 2017 Author Share Posted January 14, 2017 Tested it. Cooked with it. Played with it. WORKS PERFECT! Words can not describe how appreciative I am right now... Thank you so much my friend, it would be a great honor if I could add you as a contributor when the character goes live on Steam. If there is anything I can ever do for you, just let me know. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now