Jump to content

Recommended Posts

  • Developer

@Ipsquiggle Here is a brain-teaser for you, how do you set an animation to play in the background rather than on the foreground?

Example, most programming languages allow you to use a function like SendToBack to send a graphical item to the back of the field. Is this possible?

There's two things which "back" could mean:

The first is the layering of symbols within an animation. And in Don't starve, this is handled entirely by the animation export and can't be modified at runtime. So for example, if a character's arm is "in front" of his torso, that's just the way it is. You'd have to edit the animation to affect it.

The second is the position of objects within the world, literally behind. You can get the world position of an object with inst.Transform:GetWorldPosition(), and the camera angle with TheCamera:GetHeadingTarget()*DEGREES. Using these you can figure out where "behind" is an move another object there.

Do either of those answer your question?

There's two things which "back" could mean:The second is the position of objects within the world, literally behind. You can get the world position of an object with inst.Transform:GetWorldPosition(), and the camera angle with TheCamera:GetHeadingTarget()*DEGREES. Using these you can figure out where "behind" is an move another object there.Do either of those answer your question?

This answers my question, but brings more questions. Example, I am trying to make my poison effect show behind the creature/character, so I use the Transform:GetWorldPosition() to find the location of the instance, then use TheCamera:GetHeadingTarget()*DEGREES to find the angle in which the camera is pointing, but how would I determine the position to play the animation?Example, As of now I am using the transparency of the .tex file to make the cloud appear see through because the animation is always played on the foreground rather than in the background. So if I use a poison on for example a Robin, the robin is completely engulfed by the animation not allowing players to see where it actually is located.What I am trying to do is more this animation behind the Robin one so that players get notification of a poisoned creature, but are still able to see the creature.
  • Developer

I actually just noticed Burnable:AddBurnFX() and Burnable:SpawnFX()This uses the AddChild functionality to have one prefab "attach" to another. If you search the whole project for AddBurnFX you can see a few different ways this is used. This is probably pretty close to what you want?

I actually just noticed Burnable:AddBurnFX() and Burnable:SpawnFX()This uses the AddChild functionality to have one prefab "attach" to another. If you search the whole project for AddBurnFX you can see a few different ways this is used. This is probably pretty close to what you want?

That is what I was using, but it isn't entirely what I want because once again it hinders the view of the player.
  • Developer

The layering works fine so long as one object is genuinely behind the other. You'll have to do something like this:

-- somewhere this gets added to something elseparent_inst:AddChild(poison_inst)-- somewhere this gets updatedlocal rotation = TheCamera:GetHeadingTarget()rotation = rotation + 90*DEGREES     -- This is an arbitrary amount, find the value that works for youlocal xoffset = math.cos(rotation) * 0.2local zoffset = math.sin(rotation) * 0.2poison_inst.Transform:SetPosition(xoffset, 0, zoffset)

The layering works fine so long as one object is genuinely behind the other. You'll have to do something like this:

-- somewhere this gets updatedlocal rotation = TheCamera:GetHeadingTarget()rotation = rotation + 90*DEGREES     -- This is an arbitrary amount, find the value that works for youlocal xoffset = math.cos(rotation) * 0.2local zoffset = math.sin(rotation) * 0.2poison_inst.Transform:SetPosition(xoffset, 0, zoffset)
The :AddChild part of the code wasn't needed, the second half does everything I was looking for, thank you very much.

Is there a way to access a state graph after it has been loaded, to be able to change the timeline without making a new file?Example:

State{        name = "attack",        tags = {"attack", "busy"},                onenter = function(inst, target)            inst.Physics:Stop()            inst.components.combat:StartAttack()            inst.AnimState:PlayAnimation("atk")            inst.sg.statemem.target = target        end,                timeline=        {            TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "Attack")) end),            TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "attack_grunt")) end),            TimeEvent(25*FRAMES, function(inst) inst.components.combat:DoAttack(inst.sg.statemem.target) end),        },                events=        {            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),        },    }
I want to be able to add a line to the timeline, to push an event so I can add poison damage to the spider attacks.

Is there a way to access a state graph after it has been loaded, to be able to change the timeline without making a new file?Example:

I want to be able to add a line to the timeline, to push an event so I can add poison damage to the spider attacks.
State{        name = "attack",        tags = {"attack", "busy"},                onenter = function(inst, target)            inst.Physics:Stop()            inst.components.combat:StartAttack()            inst.AnimState:PlayAnimation("atk")            inst.sg.statemem.target = target        end,                timeline=        {            TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "Attack")) end),            TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "attack_grunt")) end),            TimeEvent(25*FRAMES, function(inst) inst.components.combat:DoAttack(inst.sg.statemem.target) end),        },                events=        {            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),        },    }

this works

-- change this line to whatever you need.local newTimeEvent = GLOBAL.TimeEvent( 13*GLOBAL.FRAMES, function(inst)  end )--local SGspider = GLOBAL.require("stategraphs/SGspider")table.insert(SGspider.states.attack.timeline, newTimeEvent)GLOBAL.package.loaded["stategraphs/SGspider"] = SGspider

this works

-- change this line to whatever you need.local newTimeEvent = GLOBAL.TimeEvent( 13*GLOBAL.FRAMES, function(inst)  end )--local SGspider = GLOBAL.require("stategraphs/SGspider")table.insert(SGspider.states.attack.timeline, newTimeEvent)GLOBAL.package.loaded["stategraphs/SGspider"] = SGspider

Thanks no_signal, you are a true hero!

For the new Dem Bones Archaeology mod I need to define new text for the Skeleton Rod (mimics the Divining rod text). Anyone have a clue how to get this to apply to skeletonrod.lua?

GLOBAL.SKELETONROD =		{			COLD = "The skeleton thing is talking.",			GENERIC = "It's a skeleton thing.",			HOT = "This skeleton thing is scaring me!",			WARM = "Seems the skeleton thing is getting excited!",			WARMER = "The skeleton thing is getting HOT!",		}
(this doesn't work obviously... )

make sure your rod has

inst:AddComponent("inspectable")inst.components.inspectable.getstatus = describe
where describe is a function just like in diviningrod.lua
Got that and it's a bit more involved. I'm just not sure how to tie into it with my own text (and over ride each character's default "it's a... thing...")
local function describe(inst)    if inst.components.equippable:IsEquipped() then        if inst.closeness and inst.closeness.describe then            return string.upper(inst.closeness.describe)        end        return "COLD"    endend

Then I don't understand the problem you are having. If you set the item up like the diviningrod's strings, and you supply the game with the correct string via getstatus, then it should show the custom text for that status. If this is not the case, you need to show more code or explain the problem better.

Got that and it's a bit more involved. I'm just not sure how to tie into it with my own text (and over ride each character's default "it's a... thing...")

local function describe(inst)    if inst.components.equippable:IsEquipped() then        if inst.closeness and inst.closeness.describe then            return string.upper(inst.closeness.describe)        end        return "COLD"    endend
Not sure if this has anything to do with it, but each character has their own "speech" for the divining rod. Maybe you need to do the same with your rod as well?Example:speech_{CHARACTERNAME}.lua each of them have a specification for the diviningrod.

Not sure if this has anything to do with it, but each character has their own "speech" for the divining rod. Maybe you need to do the same with your rod as well?Example:speech_{CHARACTERNAME}.lua each of them have a specification for the diviningrod.

Yeah, they each have their own set of comments (cold, generic, warm, warmer, hot) and I'd like to put all the new phrases in the modmain if possible. I sure don't want to include all the 'speech_' files with the mod if I can help it. Something like (not working of course):
GLOBAL.STRINGS.SPEECH_WX78.SKELETONROD =		DESCRIBE =	{		SKELETONROD =		{			COLD = "SKULL EMANATIONS: LOW",			GENERIC = "IT WANTS ITS BROTHER",			WARM = "SKULL EMANATIONS: MEDIUM",			WARMER = "SKULL EMANATIONS: HIGH",			HOT = "SKULL EMANATIONS: EXTREMELY HIGH",		},			},

Edit edit.

GLOBAL.STRINGS.CHARACTERS.WX78.DESCRIBE.SKELETONROD =		{			COLD = "SKULL EMANATIONS: LOW",			GENERIC = "IT WANTS ITS BROTHER",			WARM = "SKULL EMANATIONS: MEDIUM",			WARMER = "SKULL EMANATIONS: HIGH",			HOT = "SKULL EMANATIONS: EXTREMELY HIGH",		}
edit: ****ing forum turning it into lowercase for some reason. Edited by Heavenfall

--- EDIT ---Irrelevant post.Heavenfall is on a more accurate path to finding the solution.--- EDIT 2 ---strings.lua

--these are broken out into their own files for ease of editingSTRINGS.CHARACTERS ={	GENERIC = require "speech_wilson",	WAXWELL = require "speech_maxwell",	WOLFGANG = require "speech_wolfgang",	WX78 = require "speech_wx78",	WILLOW = require "speech_willow",	WENDY = require "speech_wendy",	WICKERBOTTOM = require "speech_wickerbottom",}
This should help you. Edited by gamer.toukotsu
Added additional information

[MENTION=55]Ipsquiggle[/MENTION]Is there any way to change local variables declared outside of component after game starts?In the hunter component, before the actual definition of component starts are 4 local variables: local HUNT_UPDATE = 2local HUNT_RESET_COOLDOWN = 5local MIN_TRACKS = 6local MAX_TRACKS = 12I need to change them after game starts via world customization options. It worked some time ago, but now it don't works at all. I try to hook to them via post init to hunter component:

  function HunterPostInit(inst)   function inst:SetNumofTracks(num1,num2)   GLOBAL.MIN_TRACKS = num1   GLOBAL.MAX_TRACKS = num2   endend
Using that function in tuning overrides like this:
	["koalefant"] = 	{							doit = 	function(difficulty)							            local hunter = require("components/hunter")										if hunter then											if difficulty == "never" then											GetWorld().components.hunter:SetNumofTracks(0,0)											elseif difficulty == "12 - 24" then											GetWorld().components.hunter:SetNumofTracks(12,24)											elseif difficulty == "16 - 28" then											GetWorld().components.hunter:SetNumofTracks(16,28)											elseif difficulty == "20 - 32" then											GetWorld().components.hunter:SetNumofTracks(20,32)											elseif difficulty == "24 - 36" then											GetWorld().components.hunter:SetNumofTracks(24,36)											elseif difficulty == "28 - 40" then											GetWorld().components.hunter:SetNumofTracks(28,40)											elseif difficulty == "32 - 44" then										    GetWorld().components.hunter:SetNumofTracks(32,44)											elseif difficulty == "48 - 52" then										    GetWorld().components.hunter:SetNumofTracks(48,52)											elseif difficulty == "60 - 68" then										    GetWorld().components.hunter:SetNumofTracks(60,68)											end										end									end,				},
Can you rewrite the component so all variables will be in component definition, it will be much easier to mod it after that from modmain file. Edited by _Q_

Thanks, this looks like it's actually working. I had something similar, but is nullified all the rest of his speech. Putting the whole thing in one line seems to have done it. Sweet!

Edit edit.

GLOBAL.STRINGS.CHARACTERS.WX78.DESCRIBE.SKELETONROD =		{			COLD = "SKULL EMANATIONS: LOW",			GENERIC = "IT WANTS ITS BROTHER",			WARM = "SKULL EMANATIONS: MEDIUM",			WARMER = "SKULL EMANATIONS: HIGH",			HOT = "SKULL EMANATIONS: EXTREMELY HIGH",		}
edit: ****ing forum turning it into lowercase for some reason.

There was a huge difference to what you were doing first and what you are doing now. If you do something like GLOBAL.STRINGS.CHARACTERS.WX78.DESCRIBE = then you are replacing that whole piece of the table with a new variable, effectively deleting all previous entries in the GLOBAL.STRINGS.CHARACTERS.WX78.DESCRIBE table.

  • Developer

@Ipsquiggle

Is there any way to change local variables declared outside of component after game starts?

Can you rewrite the component so all variables will be in component definition, it will be much easier to mod it after that from modmain file.

There's certainly not a straightforward way to do this; and you are quite correct, I need to go through the whole codebase in the near future and extract all the magic numbers, hidden locals, nameless functions, etc. so that you guys can hook them and overwrite them.

There's some large tasks on my plate at the moment, but it's something I'm definitely going to get done eventually.

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
×
  • Create New...