Clopen

  • Content Count

    55
  • Joined

  • Last visited

 Content Type 

Profiles

Forums

Downloads

Klei Bug Tracker

Game Updates

Hot Lava Bug Reporter

Posts posted by Clopen


  1. Hello all,

    I'm trying to make a new kind of bush that's basically exactly the same as the berry bush ("berrybush" prefab) only with something other than berries on it.

    I have the images, Spriter shows the animations work, but in the game itself there is a problem with picking the "berries" off the bush - both before and after picking it, it still shows the same amount of "berries" on it.
    From looking at the code I saw that there is a setberries() function which determines the amount of berries shown.
    To do that it shows/hides animations called "berries", "berriesmore" and "berriesmost":

    local function setberries(inst, pct)
        if inst._setberriesonanimover then
            inst._setberriesonanimover = nil
            inst:RemoveEventCallback("animover", setberries)
        end
    
        local berries =
            (pct == nil and "") or
            (pct >= .9 and "berriesmost") or
            (pct >= .33 and "berriesmore") or
            "berries"
    
        for i, v in ipairs({ "berries", "berriesmore", "berriesmost" }) do
            if v == berries then
                inst.AnimState:Show(v)
            else
                inst.AnimState:Hide(v)
            end
        end
    end

     

    And it seems that the problem is that my animation data doesn't have these three animations.
    I used Krane to extract the Spriter project from the game files, and the project contains all the animations except those three, it seems.
    Opening the original bush's anim.bin file in a hex editor shows that these three terms are present in it (at the end of the file), but after extracting it, searching the contents of the extracted files for them yields nothing in any file.

    I've tried adding these three animations to the project with what I think they should contain, but it made little difference, and what it did do made no sense to me.

    Can someone please help me understand what's going on here, or at least how I can go about making my own somethingbush?

    Thanks in advance.


  2. @Ultroman I think he meant "lightning" rather than "lighting." =)

    There's actually a debug key that summons lightning at the position of the mouse cursor (Shift+F5).
    This is what it does:

    local pos = TheInput:GetWorldPosition()
    TheWorld:PushEvent("ms_sendlightningstrike", pos)

    I'd include the code for binding it to the Shift+F5 key, but that bit uses a debug key so it's not what you want.
    For that you should do like Ultroman said and copy it off of a mod that has something done on key press.

    There's also one thing you should note: while the lightning is summoned at the given position pos, it can hit somewhere else nearby instead - namely, it can hit the summoning player. This is because lightning bolts randomly target nearby points of interest I guess, or maybe specifically the player.

    So you might want to make your character immune to lightning, or make it a pre-known risk.
    You can probably give your character temporary lightning immunity just for that lightning strike, but personally I don't like that idea as it affects other lightning strikes as well.

    You can look into how the event itself works to circumvent the location randomization; I haven't looked into that but it should be possible.


  3. I've created two sets of trinket-like items: toys and plushies.

    First I made the toys, for which I made a single Spriter project with all of them and created a generic generation function for the prefabs.
    These work 100%.

    Then I made a copy of this file for the plushies and created a new Spriter project for them in a similar fashion.
    For some reason, only the first item in the plushies list (bunny) has the correct image when dropped on the ground.
    The second item (elephant) has the image of the bunny, and the rest are invisible.
    This is despite the fact that there is absolutely no special treatment for any of them.
    I.e. the code simply has a list of IDs, of which "bunny", "elephant" and "fox" are three, and the Spriter project has an entity for each plush with its name and an "idle" animation with the still image.

    Here is a screenshot with three plushies and three toys, both in the inventory and on the ground:

    Problem.thumb.jpg.ec1a7eb3531a7a0b330be9a653c6fd87.jpg

    You can see the name of the second bunny on the floor is "Plush Elephant", which in the inventory does show up as an elephant (second item on the left).
    And here is a screenshot of the Spriter project.

    5ba063ab3e92e_Problem-Spriter.thumb.jpg.1195f7c4980da2df1123f461c2230036.jpg

    I have closed the Spriter project, deleted the anim file, exited the game, invoked the autocompiler manually, saw it export the plushies, ran the game again and checked once more and it's still like this, so I know for sure that what I'm seeing in-game represents the current state of the code and the Spriter project.

    All the inventory images work fine, the names are good, just the images for when the items are on the ground are wrong in this weird fashion.

    And once again, I use the same exact mechanism for the toys and they work just fine.
    I'm really stumped here.

    Here is the code for the plushies (plushies.lua):

    local PLUSHNAMES =
    {
    	bunny = "Plush Bunny",
    	elephant = "Plush Elephant",
    	fox = "Plush Fox",
    	kitty = "Plush Kitty",
    	lion = "Plush Lion",
    	puppy = "Plush Puppy",
    	raccoon = "Plush Raccoon",
    	trex = "Plush T-Rex",
    	turkey = "Plush Turkey",
    }
    
    
    local assets =
    {
    	Asset("ANIM", "anim/plushies.zip"),
    }
    
    for id, name in pairs(PLUSHNAMES) do
    	local prefabid = "plush_"..id
    	table.insert(assets, Asset("ATLAS", "images/inventoryimages/"..prefabid..".xml"))
    	table.insert(assets, Asset("IMAGE", "images/inventoryimages/"..prefabid..".tex"))
    end
    
    
    local function MakePlush(id, name)
    	local prefabid = "plush_"..id
    	
    	local function fn()
    		local inst = CreateEntity()
    		
    		inst.entity:AddTransform()
    		inst.entity:AddAnimState()
    		inst.entity:AddSoundEmitter()
    		inst.entity:AddNetwork()
    		
    		MakeInventoryPhysics(inst)
    		
    		inst.AnimState:SetBank(id)
    		inst.AnimState:SetBuild("plushies")
    		inst.AnimState:PlayAnimation("idle")
    		
    		inst:AddTag("plush")
    		
    		inst.entity:SetPristine()
    		
    		if not TheWorld.ismastersim then
    			return inst
    		end
    		
    		inst:AddComponent("inspectable")
    		
    		inst:AddComponent("inventoryitem")
    		inst.components.inventoryitem.atlasname = "images/inventoryimages/"..prefabid..".xml"
    		
    		MakeHauntableLaunchAndSmash(inst)
    		
    		return inst
    	end
    	
    	STRINGS.NAMES[string.upper(prefabid)] = name
    	
    	return Prefab(prefabid, fn, assets, prefabs)
    end
    
    local ret = {}
    for id, name in pairs(PLUSHNAMES) do
    	table.insert(ret, MakePlush(id, name))
    end
    
    return unpack(ret)

     

    And for reference, here is the code for the toys (toys.lua):

    local TOYNAMES =
    {
    	cube = "Rubik's Cube",
    	ball = "Toy Ball",
    	-- legopieces = "Lego Pieces", -- Commented out for manual insertion as a repairer
    	vroom = "Toy Car",
    	tablet = "Tablet",
    	bucket = "Bucket and Shovel",
    	duck = "Rubber Duck",
    	frisbee = "Frisbee",
    	armymen = "Army Men",
    }
    
    
    local assets =
    {
    	Asset("ANIM", "anim/toys.zip"),
    }
    
    for id, name in pairs(TOYNAMES) do
    	local prefabid = "toy_"..id
    	table.insert(assets, Asset("ATLAS", "images/inventoryimages/"..prefabid..".xml"))
    	table.insert(assets, Asset("IMAGE", "images/inventoryimages/"..prefabid..".tex"))
    end
    
    
    local function MakeToy(id, name, repairer)
    	local prefabid = "toy_"..id
    	
    	local function fn()
    		local inst = CreateEntity()
    		
    		inst.entity:AddTransform()
    		inst.entity:AddAnimState()
    		inst.entity:AddSoundEmitter()
    		inst.entity:AddNetwork()
    		
    		MakeInventoryPhysics(inst)
    		
    		inst.AnimState:SetBank(id)
    		inst.AnimState:SetBuild("toys")
    		inst.AnimState:PlayAnimation("idle")
    		
    		inst:AddTag("molebait")
    		inst:AddTag("cattoy")
    		inst:AddTag("toy")
    		
    		inst.entity:SetPristine()
    		
    		if not TheWorld.ismastersim then
    			return inst
    		end
    		
    		inst:AddComponent("inspectable")
    		inst:AddComponent("stackable")
    		inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM
    		
    		inst:AddComponent("inventoryitem")
    		inst.components.inventoryitem.atlasname = "images/inventoryimages/"..prefabid..".xml"
    		
    		if repairer then
    			inst:AddComponent("repairer")
    			inst.components.repairer.repairmaterial = MATERIALS.PLASTIC
    			inst.components.repairer.healthrepairvalue = TUNING.REPAIR_CUTSTONE_HEALTH
    		end
    		
    		MakeHauntableLaunchAndSmash(inst)
    		
    		return inst
    	end
    	
    	STRINGS.NAMES[string.upper(prefabid)] = name
    	
    	return Prefab(prefabid, fn, assets, prefabs)
    end
    
    local ret = {}
    for id, name in pairs(TOYNAMES) do
    	table.insert(ret, MakeToy(id, name))
    end
    
    table.insert(ret, MakeToy("legopieces", "Lego Pieces", true))
    
    return unpack(ret)

     

    Any help would be greatly appreciated.
    Thanks in advance.


  4. I've added a custom item and a recipe for it.
    The item works fine, shows up in the inventory and on the ground, and it gets cooked in the crock pot correctly as well, but when the cooking is finished the pot looks empty. Still harvestable and gives the item, but the item is invisible on it.

    I've searched for this issue and seen quite a bit about it, and the most current solution seems to be found in this tutorial:

    Unfortunately, I've followed it meticulously and it still doesn't work.
    I have the following folder structure:

    • Mod directory
      • anim
        • macncheese.zip
      • exported
        • macncheese
          • macncheese.scml
          • macncheese.zip (created when the autocompiler was run)
          • macncheese
            • macncheese-0.png

    I used the meat stew image with altered colors for now.
    I've attached an image of the Spriter project, and here are its contents:

    Spoiler
    
    <?xml version="1.0" encoding="UTF-8"?>
    <spriter_data scml_version="1.0" generator="BrashMonkey Spriter" generator_version="b5">
        <folder id="0" name="macncheese">
            <file id="0" name="macncheese/macncheese-0.png" width="192" height="192" pivot_x="0.494819" pivot_y="0.380829"/>
        </folder>
        <entity id="0" name="macncheese">
            <animation id="0" name="idle" length="1000">
                <mainline>
                    <key id="0">
                        <object_ref id="0" name="macncheese" folder="0" file="0" abs_x="1.005181" abs_y="0.119171" abs_pivot_x="0.494819" abs_pivot_y="0.380829" abs_angle="360" abs_scale_x="1" abs_scale_y="1" abs_a="1" timeline="0" key="0" z_index="0"/>
                    </key>
                </mainline>
                <timeline id="0" name="macncheese">
                    <key id="0" spin="0">
                        <object folder="0" file="0" x="1.005181" y="0.119171"/>
                    </key>
                </timeline>
            </animation>
        </entity>
    </spriter_data>

     

    I've attached the exported/ folder with all the relevant files.
    If anyone has any idea what I'm doing wrong, I'd really appreciate some help.

    Thanks in advance.

    Spriter.png

    exported.zip


  5. I've added some components to certain prefabs which are stackable.
    I'd like to make it so that when two stacks of these prefabs are combined, the properties of the extra component would be decided by a custom piece of code.
    At the moment, one item remains and its stack size increases, while the other disappears, which means the properties are decided by whichever item happens to remain.
    Usually I would want these properties to be reset to some minimum/maximum instead.

    Is it possible to do this?

    Thanks in advance. =)


  6. A follower creature I made seems to work OK, but the running and walking speeds I set are reversed.
    At least, I think that's the case, since it starts walking at its running speed and then switches to walking speed when my distance from it grows.

    Here are the relevant parts of the code:

    Prefab

    local function init_prefab()
    	-- ...
    	inst:AddComponent("follower")
    	-- ...
    	inst:AddComponent("locomotor")
    	inst.components.locomotor.walkspeed = 5
    	inst.components.locomotor.runspeed = 10
    	-- ...
    	return inst
    end

    Stategraph

    local states =
    {
    	-- ...
    
    	State{
    		name = "walk_start",
    		tags = {"moving", "canrotate"},
    		
    		onenter = function(inst) 
    			inst.AnimState:PlayAnimation("walk_pre")
    		end,
    		
    		events =
    		{   
    			EventHandler("animover", function(inst) inst.sg:GoToState("walk") end ),
    		},
    	},
    	
    	-- This handles the running state.
    	State{
    		
    		name = "walk",
    		
    		-- Our running animation is also safe to be rotated.
    		tags = { "canrotate", "moving" },
    		
    		onenter = function(inst, playanim)
    			
    			-- When entering this state, we now play a looping run animation.
    			inst.AnimState:PlayAnimation("walk_loop", true)
    			
    			-- Tell the locomotor that it is ok to start running.
    			inst.components.locomotor:WalkForward()
    		end,
    	},
    	
    	State{
    		name = "walk_stop",
    		tags = {"canrotate"},
    		
    		onenter = function(inst) 
    			inst.components.locomotor:StopMoving()
    			inst.AnimState:PlayAnimation("walk_pst")
    		end,
    		
    		events=
    		{   
    			EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ),
    		},
    	},
    
        State{
    
            name = "run",
            tags = {"moving", "running", "canrotate"},
    
            onenter = function(inst)
                inst.components.locomotor:RunForward()
                inst.AnimState:PlayAnimation("walk_loop")
            end,
    		
    		ontimeout = function(inst)
                inst.sg:GoToState("walk")
            end,
    		
    		events=
            {   
                EventHandler("animover", function(inst) inst.sg:GoToState("walk") end ),        
            },
    	
        },
    	
    -- ...
    }
    
    local event_handlers =
    {
        EventHandler("locomote", function(inst) 
            if not inst.sg:HasStateTag("busy") then
                local is_moving = inst.sg:HasStateTag("moving")
                local wants_to_move = inst.components.locomotor:WantsToMoveForward()
                if not inst.sg:HasStateTag("attack") and is_moving ~= wants_to_move then
                    if wants_to_move then
    					local should_run = inst.components.locomotor:WantsToRun()
    					if should_run then
    						inst.sg:GoToState("run")
    					else
    						inst.sg:GoToState("walk")
    					end
                    else
                        inst.sg:GoToState("idle")
                    end
                end
            end
        end),
    }

    Brain

    local MIN_FOLLOW_DIST = 0
    local MAX_FOLLOW_DIST = 6
    local TARGET_FOLLOW_DIST = 6
    -- ...
    
    -- In the OnStart function, under a root PriorityNode
    Follow(self.inst, function() return self.inst.components.follower.leader end, MIN_FOLLOW_DIST, TARGET_FOLLOW_DIST, MAX_FOLLOW_DIST, true),

     

    Of course, I could just reverse the values of the walking and running speeds, which is what I've done for now in order for it to work decently, but that's clearly not the best solution here...

    Any help would be appreciated.
    Thanks in advance. ^_^


  7. I've added a Wander behavior to my creature, and it uses it, but instead of wandering around the given home position it keeps returning exactly to it every time.
    I.e. it's on a loop of "go to a random point at wander distance" --> "go back to home point".
    It would make a kind of star or asterisk shape if you drew the lines it traverses, where I'd expect something more like random lines between points on a circle whose center is the home location.

    I don't recall seeing creatures in the game doing this, so I'm guessing there's something wrong with what I'm doing, which is this:

    Wander(self.inst, function() return self.inst.components.knownlocations:GetLocation("anchor") end, MAX_WANDER_DIST)

    The "anchor" position is fixed while this behavior is active, and at the moment MAX_WANDER_DIST = 5, but I've tried adjusting it and no matter what value I chose, it would always move like that, just up to a different distance from the center.

    I saw the same kind of behavior when I used Leash instead - which, by the way, is different from Wander how, exactly?
    I'm not sure I get the difference.

    Any help would be appreciated.
    Thanks in advance.


  8. Thank you! ^_^

    Indeed, that was exactly what I needed, though I ended up using the component postinits.
    In case it'll be of use to someone, here is how I added save/load capabilities to a new field I made for the inventoryitem component:

    local function InventoryItemInit(component)
    	if component ~= nil then
    		local oldSaveFunction = component.OnSave
    		if oldSaveFunction == nil then oldSaveFunction = function(self) return nil end end
    		component.OnSave = function(self)
    			data = oldSaveFunction(self)
    			if self.creator ~= nil then
    				if data == nil then data = {} end
    				if data.creator == nil then
    					data.creator = self.creator
    				end
    			end
    			return data
    		end
    		
    		local oldLoadFunction = component.OnLoad
    		if oldLoadFunction == nil then oldLoadFunction = function(self, data) end end
    		component.OnLoad = function(self, data)
    			oldLoadFunction(data)
    			if data ~= nil and data.creator ~= nil and self.creator == nil then
    				self.creator = data.creator
    			end
    		end
    	end
    end
    
    AddComponentPostInit("inventoryitem", InventoryItemInit)

    Oh, and of course, I always make sure I don't access nil.
    A game is much less fun when it crashes.


  9. As part of my effort to mark who (i.e. which character prefab) crafted/cooked a certain item, I tried adding a tag to the item, and when that didn't work, a custom component that just has the name of the creator's prefab.

    Adding the component did at least save the added data, but it doesn't load it.
    My guess is that after instantiation, the saved data is passed to the OnLoad function of all the object's components, and since the prefab itself (in my tests, just a normal axe) doesn't add that component on its own, the data doesn't get loaded, even though the component data is there.

    The question therefore is: how do I add custom data, in any way, to an instance of an existing prefab without making changes to the code of that prefab?
    I want to add this "creator" tag/component to every item with finite uses and every cooked item.
    I don't want to change all of the relevant existing prefabs or components for this for obvious reasons.

    Any help would be greatly appreciated. =)


  10. I have two similar problems.

    Tagging cooked items:
    I'd like to tag all foodstuffs prepared by a specific character I'm making, to mark that it was prepared by her for later use.

    I thought to wrap the existing ACTIONS.COOK.fn function, but it doesn't return the prepared item.
    I'd rather not replace it altogether since that is more likely to clash with other mods.
    I'd also rather not modify each of the components capable of cooking, also to allow support with other mods that may add more cooking options.

    It seems like the most sensible place to make the change would be with the COOK action somehow, but like I said, I don't know how to do that in a non-invasive manner.
    Is there some OnFinishedCooking function or something of the sort somewhere that gives the created product and the chef who made it?
    I think the lesser evil here would be to modify the cooker and stewer components (how do I do that, by the way?), but I'd appreciate some experienced input here.

    Tagging built items:
    The same thing, really, just for items being built (crafted).

    I'd also like to add a tag saying they were crafted by a specific (different) character.
    There's a BUILD action, but it doesn't return the created product either, same as with the COOK action.
    Even more problematic is that here I think I have to change Builder:DoBuild (i.e. overwrite it completely to make the modifications to it), which once again, is not as compatible with other mods as wrapping. Actually, it's also more likely to require changing when the game is updated, since any change to the overridden function would require changing the overriding function as well.

     

    So how do you think I should go about doing these two things?

    Thanks in advance.


  11. Wow, thank you! :o

    I was starting to think I'd need to create a new Steam account and buy another copy of the game just so I could test my mod. =\
    I get that they don't want to allow the same user to use the same copy of the game multiple times, but there should really be a solution for doing this for testing.
    For example, they could have allowed multiple copies of the game to run on the same computer and allowed the same client to connect to its localhost multiple times (I actually tried doing that but I didn't get it to work).

    I'll download Discord later today and contact you when I can.
    I spend most of the time with my girlfriend when she's home so I can only work on this when she's not around. ^_^;

    Thanks again. =)


  12. I'm developing a mod whose main features require two players.
    I therefore need to have two players in the game, but I haven't been able to find a way to use my single Steam copy of Don't Starve Together to log in to the game twice.

    I'm using two computers for this, and I've tried:

    • Running both clients in offline mode, hosting a local LAN game on one and connecting with the other - no games show up on when browsing with the second client.
    • Running one client online and the other offline with the hosted game being hosted by the online client and the game set as either online or local - still can't find the game when browsing with the other.
    • Running one client online and the other offline with the hosted game being hosted by the offline client - I get an error when I click the Host Game option (it says "WARNING" at the top but it only lets you exit or report an issue.)
    • Running both clients online - this naturally causes one of the clients to disconnect from Steam, and although both DST clients manage to connect, when I start the second one I get a client token error, which is really to be expected.

    I haven't been able to find out why I can't see the LAN game (before you ask - both computers are on the same WiFi network) and I'm not sure if that's even a problem or if you can't run the game on the same account twice even in offline mode on purpose.

    So... how do I go about testing my mod?
    Please don't say "find another player;" I only have one friend who has the game and this mod is supposed to be a surprise for her; and I won't bother others with this since development will take time and I'll need to test a lot of things.

    Thanks in advance. =)