Jump to content

Recommended Posts

Hello! I have an item i need some help with.

I need this item to be only usable by my character. i'm okay with the item being holdable by other characters, but the ability to use the item is what i want locked to the character. i saw a post about this earlier, but the post linked to another post that answered the question, the problem was that post was blank. incase that was confusing, basically there was no answer to that post.

If possible, i would like it working so that if my character uses it, sanity to all is increased or some kind effect, but if wilson(or any other character for that matter) uses it, then he will say something like "i am not skilled enough to use this"

Any idea how to get this working?

(the item is a copy of the pan flute as of now, so it currently works just like one.)

Edited by Augustusc
Link to comment
https://forums.kleientertainment.com/forums/topic/70102-item-code-question/
Share on other sites

I guess it's possible since as far as i know, wickerbottom books work the way you want.

 

If i understand how it work, you have to add a tag to your character, like, i don't know, "greatmusician", and make that if you have the tag, you could use the item, and if you haven't, you couldn't. I guess you could find some examples in the game file, because i'm less familiar with this part.

You could also use the same tag as a way to make the recipe exclusive to one character. For example,


Recipe("spear_wathgrithr", {Ingredient("twigs", 2), Ingredient("flint", 2), Ingredient("goldnugget", 2)}, RECIPETABS.WAR, TECH.NONE, nil, nil, nil, nil, "valkyrie")

This recipe is only accessible to someone with the valkyrie tag. Wigfrid has it so she could make the recipe. If you add the "valkyrie" tag to your character, he will be able to do the recipe too.

I wouldn't know how to write this as code, but would it work if i added a tag to my character, and made an If statement where if the player has the tag, then they can use the item, but if they don't ahve the tag, they will say "i cant use this"?

Is it that simple? or am i attempting to do something that is actually impossible, i would think it would be easy, but unfortunately, everyone seems to have trouble answering my question here.

@Augustusc Okay, so I will answer your question ;)

There are several ways of achieving what you want. Some are easy and others are more complicated.

You said your instrument is a copy of panflute right now.
So the easiest way would be using the instrument component of the pan flute.
If you take a look at the component/instrument.lua, you see the Play function.
If you set a "onplayed" function, this will be called first. And if you set a onheard function, this will play after that.

So the ways that come up to my mind first are:
1) listen for picking up of your instrument. Everytime a character that has not the needed Tag picked it up, you set the onheard function to nil. And in the onplayed function you can add your "I'm not skilled enough".  The downside is, that listening for picking up might be error prone... I did not tested it yet, but I don't know what happens when are character dies or other special cases.
2) Mod the Play function from instrument component directly. You can add a Tag and instrument check at the beginning of the Play function. If it is your instrument and the char has the tag Or it is not your instrument, do the rest of the original function. If he does not have the tag and it is your instrument, write "not skilled enough".

I personally prefer modding the component, because it is quite easy and not that error prone.  But modding a whole component (which is also used by other items) just to make one new item work, might be a bit overkill.

What do you think?
There might be better and/or more complicated solutions, but these are the two that come in my mind first.
 

Edited by Serpens

The modding component code would be (put it in modmain.lua):
 

AddComponentPostInit("instrument",function(self)
    local Old_Play = self.Play
    self.Play = function(self,musican)
        if musican and self.inst and (not self.inst:HasTag("myinstrument") or (self.inst:HasTag("myinstrument") and musican:HasTag("mymusican"))) then
            return Old_Play(self,musican)
        else
            if musican.components and musican.components.talker then
                musican.components.talker:ShutUp()
                musican.components.talker:Say("Im not skilled enough")
            end
            return false -- Im not sure if returning false here will have an effect. Try it out, you can also try to return true instead
        end
    end
end)

edit:
I did not test this, so it could contain errors, if so please tell me the error and I will fixt it ;)

Edited by Serpens

@Serpens I think it would be better to go with modding the component. i plan to eventually make a bunch of instruments, all of which i want to make sure only my character with the tag can use.

(while typing this, you replied with the lovely piece of coding, thank you for that! I will test it as soon as i can, and i will reply here with the results)

Edited by Augustusc

If you use

local function AugustusPlayPatch(sg)
	local old = sg["actionhandlers"][GLOBAL.ACTIONS.PLAY]["deststate"]
	sg["actionhandlers"][GLOBAL.ACTIONS.PLAY]["deststate"] = function(inst, action)
		if action.invobject ~= nil and (action.invobject:HasTag("augustus") and not inst:HasTag("augustus")) then
			if inst.components.talker ~= nil then
				inst.components.talker:Say("I don't know how to play this.")
			end
			return nil
		end
		return old(inst, action)
	end
end

AddStategraphPostInit("wilson", AugustusPlayPatch)
AddStategraphPostInit("wilson_client", AugustusPlayPatch)

then instruments with the tag "augustus" can only be played by players with the tag "augustus".

 

The other way the player will suddenly stop playing the instrument in the middle of the play.

since this is an error that has nothing to do with modmain code, we need the mentioned script (august_flute.lua), to tell you what is wrong.

But I'm sure you can also fix it yourself ;)
Read the error. It says there is something wrong with the variable "prefabs" in line 84.
Search for this line and compare it to the original panflute. Maybe you find the problem then ;)

Your line 84 is:
return Prefab("common/inventory/august_flute", fn, assets, prefabs)

while the one from panflute is:
return Prefab("panflute", fn, assets)

and you don't notice the difference wich has to do with the variable "prefabs"? =P

I'm not that familar with "return Prefab(..", why you added "prefabs" there?

Edited by Serpens

So i got the error to go away, thanks @Serpens (I guess they changed the code on me, last time i checked, that "prefabs" thing was a par tof the code)

New problem. the flute can still be play by others, wilson plays it just fine, i tried adding the tag i to the flute using:

inst:AddTag("august_skill")

But that didn't change anything...

 


from a short look at your modmain, you used darkxeros code wrong:

if action.invobject ~= nil and (action.invobject:HasTag("august_skill") and not inst:HasTag("august_skill")) then

You are checking here both times for the tag "august_skill", but your instrument does not have this Tag.
So change this line for the instrument to the correct Tag.

Edited by Serpens

oh my gosh. im such an idiot! thank you all so much!

Now that my question has been answered, i have a super minor question.

would it be possible to have it so each character says something different about not being able to play it?

if it isn't. thats fine, im just wondering where this code could take me if I want to apply it to other items.

39 minutes ago, Augustusc said:

oh my gosh. im such an idiot! thank you all so much!

Now that my question has been answered, i have a super minor question.

would it be possible to have it so each character says something different about not being able to play it?

if it isn't. thats fine, im just wondering where this code could take me if I want to apply it to other items.

I'm not familiar with character modding, but take a look at some character mods, how they assigned the things the new character should say, when examinine sth.

I think it works ~ like this:
Just add such strings to your modmain, should be something like STRINGS.DESCRIBE.WILSON.GHOST.
So create your own String system, like STRINGS.MYINSTRUMENT.WILSON and use it (I think you can define it in modmain, putting GLOBAL. in front of it.)
And in your AugustusPlayPatch function, try something like
doer.components.talker:Say(_G.GetString(doer, "ANNOUNCE_TRAP_WENT_OFF"))
(don't know it it will work, when you replace the announce_trap thing with your string. Try it out and if it does not work, take a look at other mods)

Edited by Serpens
On 25 сентября 2016 г. at 2:57 AM, DarkXero said:

Whenever you read "GLOBAL", assume modmain.

The line _G=_G or GLOBAL and using _G makes any code multipurpose. I add this line at the beginning of each my modmain. So if you will add this line to your code examples, people will be able to copy&paste it to any file (modmain, prefab, component etc). :) 

I know, there is also "AddStategraphPostInit". But _G just makes the code shorter I guess. Easier to read and understand.
 

Edited by Maris

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