AfrostLord Posted July 1, 2015 Share Posted July 1, 2015 Right now, I've made a structure that is essentially just a drying rack that looks different and is crafted with different materials. I want to make this structure have different dryable items and different products, and also give it collision (i.e. I don't want to be able to walk through it); I also want to edit the ingame name of the drying function (i.e. when i mouse over the structure with an applicable item, it should say "Extract" instead of "Dry"). Changing the prefabs in the drying rack.lua didn't really do anything. How do I go about doing this stuff? Link to comment Share on other sites More sharing options...
NoobModder Posted July 2, 2015 Share Posted July 2, 2015 I'll ask my friend Mobbstar for you, but he's currently gone for another half week. Hang in there and if help doesn't come, I will save you. Good luck with modding Link to comment Share on other sites More sharing options...
Mobbstar Posted July 4, 2015 Share Posted July 4, 2015 @AfrostLord, first of all, make sure you have a mod folder set up and place your prefab files in the scripts/prefabs folder there. If you need to understand Lua better, try these. To make something a solid structure, use the following in the main function (usually called "fn"):MakeObstaclePhysics(inst, RADIUS) where radius would be something between .1 (less than Wilson's hip size) and .8 (dromedary size ) I'm not sure drying itself is the easiest way to do this. You see, in order to dry something, you need to place something dryable on a dryer. Instead, you should make your own component for extractable items and add it to them using AddPrefabPostInit. Copying most of dryable could work. In order to have a unique way of using those items, you need a custom action in adition to the custom component. Example of a custom action (in modmain.lua):local ACTIONS = GLOBAL.ACTIONS --you only need these two lines once in the modmain.lua, ideally at the toplocal STRINGS = GLOBAL.STRINGS --they're so you need not place "GLOBAL." in front of those words every time ACTIONS.USESTIM = GLOBAL.Action() --view the parameters possible in action.luaACTIONS.USESTIM.str = "Inject" --what word is displayed?ACTIONS.USESTIM.id = "USESTIM" --same name as after "ACTIONS."ACTIONS.USESTIM.fn = function(act)--you can see the data possibly available in "act" in bufferedaction.lua--use this to trigger things in the item component, the extraction device or the playerendSTRINGS.ACTIONS.USESTIM = "Inject" --you need to declare the displayed word twice I think Actions are a bit of an hit-and-miss because other properties of that prefab might interfere. If it has no components other than inventory (and probably a custom dryer to allow harvesting instead of simply dropping the product), then it should be fine. Also, the keyword "extract" reminds me of this (I think it's abandoned). It's probably not exactly what you had in mind, but make sure not to use the same component or action names (for the sake of mod compatibility). Ask when an issue arrive (you can @Mention me or other modders by marking any of that person's posts and copying the resulting snippet into your message). Link to comment Share on other sites More sharing options...
AfrostLord Posted July 4, 2015 Author Share Posted July 4, 2015 @Mobbstar, local function Override(inst) print("postinit loaded") local function monster() local inst = common() inst:AddComponent("juice") inst.components.juice:SetProduct("brainjuice") inst.components.juice:SetDryTime(TUNING.DRY_FAST) return instendend AddPrefabPostInit("rabbit",Override) So to add the component what I have to put this in modmain.lua, correct? It hasn't crashed the game so I assume it is. I'm really confused about the action thing. Am I supposed to just copy it to modmain? Am I supposed to replace USESTIM with the prefab name, or is it irrelevant? Do I leave GLOBAL.action() as it is? (actions.lua says that DRY = Action(), among others). Right now, this is what I put in. Did I even use the right bufferedactions thing? ACTIONS.USESTIM = GLOBAL.Action()ACTIONS.USESTIM.str = "Extract"ACTIONS.USESTIM.id = "USESTIM"ACTIONS.USESTIM.fn = function(act)function BufferedAction:Do() if self:IsValid() then local success, reason = self.action.fn(self) if success then if self.invobject and self.invobject:IsValid() then self.invobject:OnUsedAsItem(self.action) end self:Succeed() else self:Fail() end return success, reason endendend What exactly do I put in the structure's prefab to make it perform the action? Link to comment Share on other sites More sharing options...
Mobbstar Posted July 5, 2015 Share Posted July 5, 2015 @Mobbstar, local function Override(inst) print("postinit loaded") local function monster() local inst = common() inst:AddComponent("juice") inst.components.juice:SetProduct("brainjuice") inst.components.juice:SetDryTime(TUNING.DRY_FAST) return instendend AddPrefabPostInit("rabbit",Override) So to add the component what I have to put this in modmain.lua, correct? It hasn't crashed the game so I assume it is. I'm really confused about the action thing. Am I supposed to just copy it to modmain? Am I supposed to replace USESTIM with the prefab name, or is it irrelevant? Do I leave GLOBAL.action() as it is? (actions.lua says that DRY = Action(), among others). Right now, this is what I put in. Did I even use the right bufferedactions thing? ACTIONS.USESTIM = GLOBAL.Action()ACTIONS.USESTIM.str = "Extract"ACTIONS.USESTIM.id = "USESTIM"ACTIONS.USESTIM.fn = function(act)function BufferedAction:Do() if self:IsValid() then local success, reason = self.action.fn(self) if success then if self.invobject and self.invobject:IsValid() then self.invobject:OnUsedAsItem(self.action) end self:Succeed() else self:Fail() end return success, reason endendend What exactly do I put in the structure's prefab to make it perform the action? I suppose I was talking too briefly In the function "Override" for AddPrefabPostInit, you only need the three lines regarding the juice component, everything else has no effect. (In fact, the component wasn't added so far because you constructed an unused function "monster" around that part.) The "usestim" stuff is what I used for an unfinished item in IR, you should use a different word (e.g. "extractjuice" since that would be very unique and thus be unlikely to cause incompatibility). You can leave Action() as is, though you may need to change the action priority or alike later (meaning that you would have to put data in the parentheses). The function makes no sense, sadly. You can see examples of action functions in action.lua, but keep in mind that components and stategraphs usually handle most things. Also, whether an action can even be performed is chosen in components, using the "CollectThingActions" functions (CollectSceneActions, CollectInventoryActions, etc.). Make sure the "juice" component has such a function, which, as said, can mostly be copied from "dryable". Good luck! Link to comment Share on other sites More sharing options...
NoobModder Posted July 5, 2015 Share Posted July 5, 2015 I suppose I was talking too briefly In the function "Override" for AddPrefabPostInit, you only need the three lines regarding the juice component, everything else has no effect. (In fact, the component wasn't added so far because you constructed an unused function "monster" around that part.) The "usestim" stuff is what I used for an unfinished item in IR, you should use a different word (e.g. "extractjuice" since that would be very unique and thus be unlikely to cause incompatibility). You can leave Action() as is, though you may need to change the action priority or alike later (meaning that you would have to put data in the parentheses). The function makes no sense, sadly. You can see examples of action functions in action.lua, but keep in mind that components and stategraphs usually handle most things. Also, whether an action can even be performed is chosen in components, using the "CollectThingActions" functions (CollectSceneActions, CollectInventoryActions, etc.). Make sure the "juice" component has such a function, which, as said, can mostly be copied from "dryable". Good luck!Thanks Mobbie! I think that helped him.I award you with this badge: http://www.stevefarber.com/wp-content/uploads/badge-1.png Link to comment Share on other sites More sharing options...
AfrostLord Posted July 5, 2015 Author Share Posted July 5, 2015 @Mobbstar,Thanks for the help, but one last thing. I got rabbits to count as juice and the structure to count as juicemachine (replaced every instance of dryable with juice and every instance of dryer with juicemachine) and copied the "DRY" action and renamed it "extractjuice" (and replaced "dry" with "extractjuice" in the juice prefab). I THINK it recognizes this stuff since hovering a rabbit over the structure shows "Extract". However, clicking does nothing (my character just walks to the structure). What am I doing wrong? Was I not supposed to copy the DRY action? Link to comment Share on other sites More sharing options...
Mobbstar Posted July 5, 2015 Share Posted July 5, 2015 @Mobbstar,Thanks for the help, but one last thing. I got rabbits to count as juice and the structure to count as juicemachine (replaced every instance of dryable with juice and every instance of dryer with juicemachine) and copied the "DRY" action and renamed it "extractjuice" (and replaced "dry" with "extractjuice" in the juice prefab). I THINK it recognizes this stuff since hovering a rabbit over the structure shows "Extract". However, clicking does nothing (my character just walks to the structure). What am I doing wrong? Was I not supposed to copy the DRY action? Hey, that's already pretty good! But I can't help you troubleshooting the last errors without seeing the code (or crash log, if it was crashing). Post all related code here, ideally using spoiler tags (using "special BB code" button). Link to comment Share on other sites More sharing options...
AfrostLord Posted July 5, 2015 Author Share Posted July 5, 2015 @Mobbstar,Part of modmain.luaACTIONS.extractjuice = GLOBAL.Action()ACTIONS.extractjuice.str = "Extract"ACTIONS.extractjuice.id = "extractjuice"ACTIONS.extractjuice.fn = function(act)if act.target.components.juicemachine then local ingredient = act.doer.components.inventory:RemoveItem(act.invobject) if not act.target.components.juicemachine:StartDrying(ingredient) then act.doer.components.inventory:GiveItem(product,nil, Vector3(TheSim:GetScreenPos(act.target.Transform:GetWorldPosition()) )) return false end return true endend juice.lua (dryable)local juice = Class(function(self, inst) self.inst = inst self.product = nil self.drytime = nilend) function juice:SetProduct(product) self.product = productend function juice:GetProduct() return self.productend function juice:GetDryingTime() return self.drytimeend function juice:SetDryTime(time) self.drytime = timeend function juice:CollectUseActions(doer, target, actions) if target.components.juicemachine and target.components.juicemachine:CanDry(self.inst) then table.insert(actions, ACTIONS.extractjuice) endend return juice juicemachine.lua (dryer)local function DoDry(inst) local juicemachine = inst.components.juicemachine if juicemachine then juicemachine.task = nil if juicemachine.ondonecooking then juicemachine.ondonecooking(inst, juicemachine.product) end endend local juicemachine = Class(function(self, inst) self.inst = inst self.targettime = nil self.ingredient = nil self.product = nil self.onstartcooking = nil self.oncontinuecooking = nil self.ondonecooking = nil self.oncontinuedone = nil self.onharvest = nilend) function juicemachine:SetStartDryingFn(fn) self.onstartcooking = fnend function juicemachine:SetContinueDryingFn(fn) self.oncontinuecooking = fnend function juicemachine:SetDoneDryingFn(fn) self.ondonecooking = fnend function juicemachine:SetContinueDoneFn(fn) self.oncontinuedone = fnend function juicemachine:SetOnHarvestFn(fn) self.onharvest = fnend function juicemachine:GetTimeToDry()if self.targettime thenreturn self.targettime - GetTime()endreturn 0end function juicemachine:IsDrying() return self.targettime and self:GetTimeToDry() > 0end function juicemachine:IsDone() return self.product and self.targettime and self:GetTimeToDry() < 0end function juicemachine:CanDry(juice) return not self:IsDone() and not self:IsDrying() and juice.components.juice and juice.components.juice:GetProduct() and juice.components.juice:GetDryingTime()end function juicemachine:StartDrying(juice)if self:CanDry(juice) then self.ingredient = juice.prefab if self.onstartcooking then self.onstartcooking(self.inst, juice.prefab) end local cooktime = juice.components.juice:GetDryingTime() self.product = juice.components.juice:GetProduct() self.targettime = GetTime() + cooktime self.task = self.inst:DoTaskInTime(cooktime, DoDry) juice:Remove()return trueendend function juicemachine:OnSave() if self:IsDrying() thenlocal data = {}data.cooking = truedata.ingredient = self.ingredientdata.product = self.productdata.time = self:GetTimeToDry()return data elseif self:IsDone() thenlocal data = {}data.product = self.productdata.done = truereturn data endend function juicemachine:OnLoad(data) --self.produce = data.produce if data.cooking thenself.product = data.productself.ingredient = data.ingredientif self.oncontinuecooking thenself.oncontinuecooking(self.inst, self.ingredient)self.targettime = GetTime() + data.timeself.task = self.inst:DoTaskInTime(data.time, DoDry)end elseif data.done thenself.targettime = GetTime() - 1self.product = data.productif self.oncontinuedone thenself.oncontinuedone(self.inst, self.product)end endend function juicemachine:GetDebugString() local str = nil if self:IsDrying() then str = "COOKING" elseif self:IsDone() thenstr = "FULL"elsestr = "EMPTY"end if self.targettime then str = str.." ("..tostring(self.targettime - GetTime())..")" end if self.product thenstr = str.. " ".. self.product end return strend function juicemachine:CollectSceneActions(doer, actions) if self:IsDone() then table.insert(actions, ACTIONS.HARVEST) endend function juicemachine:Harvest( harvester )if self:IsDone() thenif self.onharvest thenself.onharvest(self.inst)endif self.product thenif harvester and harvester.components.inventory thenlocal loot = SpawnPrefab(self.product)if loot thenif loot and loot.components.perishable then loot.components.perishable:SetPercent(1) --always full perishableendharvester.components.inventory:GiveItem(loot, nil, Vector3(TheSim:GetScreenPos(self.inst.Transform:GetWorldPosition())))endendself.product = nilend return trueendend function juicemachine:LongUpdate(dt)if self:IsDrying() thenif self.task thenself.task:Cancel()self.task = nilend local time_to_wait = self.targettime - GetTime() - dtif time_to_wait <= 0 thenself.targettime = GetTime()DoDry(self.inst)elseself.targettime = GetTime() + time_to_waitself.task = self.inst:DoTaskInTime(time_to_wait, DoDry)end endend return juicemachine brainmachine.lua (the structure)local assets ={Asset("ANIM", "anim/brainmachine.zip"), } local prefabs ={-- everything it can "produce" and might need symbol swaps from"brainjuice","rabbit",} local function onhammered(inst, worker)inst.components.lootdropper:DropLoot()SpawnPrefab("collapse_small").Transform:SetPosition(inst.Transform:GetWorldPosition())inst:Remove()inst.SoundEmitter:PlaySound("dontstarve/common/destroy_metal")end local function onhit(inst, worker) end local function getstatus(inst) if inst.components.juicemachine and inst.components.juicemachine:IsDrying() then return "DRYING" elseif inst.components.juicemachine and inst.components.juicemachine:IsDone() then return "DONE" endend local function onstartdrying(inst, juice) inst.AnimState:PlayAnimation("full")end local function setdone(inst, product) inst.AnimState:PlayAnimation("done")end local function ondonedrying(inst, product) inst.AnimState:PlayAnimation("done") local ondonefn -- must be forward declared, as it refers to itself in the function body ondonefn = function(inst) inst:RemoveEventCallback("animover", ondonefn) setdone(inst, product) end inst:ListenForEvent("animover", ondonefn)end local function onharvested(inst) inst.AnimState:PlayAnimation("idle")end local function onbuilt(inst)inst.AnimState:PlayAnimation("idle")end local function fn(Sim)local inst = CreateEntity()local trans = inst.entity:AddTransform()local anim = inst.entity:AddAnimState() inst.entity:AddMiniMapEntity()inst.MiniMapEntity:SetIcon( "brainmachine_map.tex" ) inst.entity:AddSoundEmitter() inst:AddTag("structure") anim:SetBank("brainmachine") anim:SetBuild("brainmachine") anim:PlayAnimation("idle") inst:AddComponent("lootdropper") inst:AddComponent("workable") inst.components.workable:SetWorkAction(ACTIONS.HAMMER) -- should be DRY inst.components.workable:SetWorkLeft(4)inst.components.workable:SetOnFinishCallback(onhammered)-- inst.components.workable:SetOnWorkCallback(onhit) inst:AddComponent("juicemachine")inst.components.juicemachine:SetStartDryingFn(onstartdrying)inst.components.juicemachine:SetDoneDryingFn(ondonedrying)inst.components.juicemachine:SetContinueDryingFn(onstartdrying)inst.components.juicemachine:SetContinueDoneFn(setdone)inst.components.juicemachine:SetOnHarvestFn(onharvested) MakeObstaclePhysics(inst, 0.3) inst:AddComponent("inspectable") inst.components.inspectable.getstatus = getstatusMakeSnowCovered(inst, .01) inst:ListenForEvent( "onbuilt", onbuilt) return instend return Prefab( "common/objects/brainmachine", fn, assets, prefabs ), MakePlacer("common/brainmachine_placer", "brainmachine", "brainmachine", "idle") Game doesn't crash. Here's the rest of the mod if the stuff in spoilers isn't enough: http://forums.kleientertainment.com/files/file/1240-wunt-the-extraterrestrial/ Link to comment Share on other sites More sharing options...
AfrostLord Posted July 8, 2015 Author Share Posted July 8, 2015 bump? Link to comment Share on other sites More sharing options...
AfrostLord Posted July 12, 2015 Author Share Posted July 12, 2015 @Mobbstar,Please? Link to comment Share on other sites More sharing options...
NoobModder Posted July 12, 2015 Share Posted July 12, 2015 Mobbstar is usually offline, XDJust wait a bit and try to get him on his profile page if he doesn't answer.He's probably busy right now or coming up with a solution for you. Link to comment Share on other sites More sharing options...
Mobbstar Posted July 12, 2015 Share Posted July 12, 2015 Sorry, I can't figure it out. The action fn doesn't fire for no obvious reason. lol nevermind, I just remembered. Actions require you to edit the stategraph if they aren't instant. Either make your action instant or modify wilsons stategraph to add a state for inserting extraction stuff. Link to comment Share on other sites More sharing options...
AfrostLord Posted July 12, 2015 Author Share Posted July 12, 2015 @Mobbstar, How do I do this? I want it to use the "doshortaction" state. I tried copying the state under a different name, putting it in a function in modmain.lua, and then putting in "AddStategraphState ("SGwilson", [function name])", same thing with AddStategraphPostinit, neither worked. Putting in the state without a function makes the game crash. Also, I've been putting in "local actionhandlers= ActionHandler(ACTIONS.extractjuice, "(name of state)")", but that didn't seem to do anything no matter where I put it (I also tried simply putting that in with doshortaction, didn't work). http://dontstarveapi.com/utility/modutil/ seems pretty vague on the stategraph stuff. Link to comment Share on other sites More sharing options...
AfrostLord Posted July 31, 2015 Author Share Posted July 31, 2015 @Mobbstar, Currently, this is what I have in my modmainlocal Action = GLOBAL.Actionlocal ActionHandler = GLOBAL.ActionHandlerlocal extractjuice = Action()extractjuice.str = "Extract"extractjuice.id = "extractjuice"extractjuice.fn = function(act)if act.target.components.juicemachine then local ingredient = act.doer.components.inventory:RemoveItem(act.invobject) if not act.target.components.juicemachine:StartDrying(ingredient) then act.doer.components.inventory:GiveItem(product,nil, Vector3(TheSim:GetScreenPos(act.target.Transform:GetWorldPosition()) )) return false end return true endend AddAction(extractjuice)AddStategraphActionHandler('wilson', ActionHandler(extractjuice, "doshortaction")) It seems to be working in that I can actually put "juice" items in the brainmachine now, which plays "doshortaction" and makes the machine start and finish drying. However, when I try to harvest the product, my character says "I can't do that!" and doesn't harvest. I do have "inst.components.juice:SetProduct("brainjuice")" in the override function and the product item itself is probably not the problem since I can spawn it in with no issue. What am I doing wrong? (if this is insufficient information the full mod is somewhere in this thread) Link to comment Share on other sites More sharing options...
AfrostLord Posted August 2, 2015 Author Share Posted August 2, 2015 Okay, I feel really stupid now, I just had to add a matching harvest action. Link to comment Share on other sites More sharing options...
Recommended Posts
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.