Jump to content

Character Specific Quickpick Perk


Recommended Posts

local myhandler = GLOBAL.ActionHandler(GLOBAL.ACTIONS.PICK, function(inst, action)

if action.target.components.pickable then

if action.target.components.pickable.quickpick or inst.prefab == "mycharacter" then

return "doshortaction"

else

return "dolongaction"

end

end

end)

AddStategraphActionHandler("wilson", myhandler)

Link to comment
Share on other sites

Everytime I see a reply from you DarkXero, my first thought is "Yay my question has been answered!"  I don't even have to read the reply to know it's something great.

 

One of these days I'll understand it enough to handle it on my own, but your assistance is always going to be appreciated

Edited by Zackreaver
Link to comment
Share on other sites

@DarkXero, Hello, back again.  I have a particular question about this script here now that I understand it better.  It looks like it's replacing the action handler for pick, and my concern is that if another mod does the same thing it could break my mod.

 

Is there a way to make the handler store the old handler in the event another mod creates one as well?  I've been able to do it with PostInit's but I'm not sure if I can do the same thing with actions as I don't know how the information is stored.

 

Of course, if I'm mistaken on the "replacing" part, then that info would be nice to know instead.

Edited by Zackreaver
Link to comment
Share on other sites

@Zackreaver, if you want to use old to append your code to the pick actionhandler, you do it like this:

AddStategraphPostInit("wilson", function(sg)	local old = sg.actionhandlers[GLOBAL.ACTIONS.PICK].deststate	sg.actionhandlers[GLOBAL.ACTIONS.PICK].deststate = function(inst, action)		if action.target.components.pickable and inst.prefab == "wilson" then			return "doshortaction"		end		return old(inst, action)	endend)

An alternative to use a custom handler and replace the pick action:

AddAction("CUSTOMPICK", "Pick", GLOBAL.ACTIONS.PICK.fn)local myhandler = GLOBAL.ActionHandler(GLOBAL.ACTIONS.CUSTOMPICK, function(inst, action)	if action.target.components.pickable then		return "doshortaction"	endend) AddStategraphActionHandler("wilson", myhandler)AddComponentPostInit("playeractionpicker", function(self)	if self.inst.prefab == "wilson" then		local old = self.SortActionList		self.SortActionList = function(self, actions, target, useitem)			if target:is_a(GLOBAL.EntityScript) and target:HasTag("pickable") then				for i, v in ipairs(actions) do					if v == GLOBAL.ACTIONS.PICK then						actions[i] = GLOBAL.ACTIONS.CUSTOMPICK						break					end				end			end			return old(self, actions, target, useitem)		end	endend)

And you can edit the component action for pickables too.

 

But the first one should do it.

Edited by DarkXero
Link to comment
Share on other sites

@DarkXero, why didn't you use AddComponentAction in the last example?

 

Example:

AddAction("CUSTOMPICK", "Pick", GLOBAL.ACTIONS.PICK.fn) local myhandler = GLOBAL.ActionHandler(GLOBAL.ACTIONS.CUSTOMPICK, function(inst, action)    if action.target.components.pickable then        return "doshortaction"    endend)  AddStategraphActionHandler("wilson", myhandler)AddComponentAction( "SCENE", "pickable", function( inst, doer, actions, right)    if doer:HasTag("prefab_name_here") then        table.insert(actions, GLOBAL.ACTIONS.CUSTOMEPICK)    endend )

Just curious as both examples would need to be ran on the client.

Edited by Kzisor
Link to comment
Share on other sites

@Kzisor, I thought I needed to do something weird with ComponentActions, like finding the function given by the game and then overwriting it. I imagined that if I did what you did, my function would overwrite the game's one, and other players wouldn't be able to use PICK anymore. So instead of thinking crazy antics, I went for the two examples I knew that would work.

 

But after reading the functions more carefully, your example is fine. Like this

local myaction = AddAction("CUSTOMPICK", "Pick", GLOBAL.ACTIONS.PICK.fn)myaction.priority = 10  local myhandler = GLOBAL.ActionHandler(GLOBAL.ACTIONS.CUSTOMPICK, function(inst, action)    if action.target.components.pickable then        return "doshortaction"    endend)   AddStategraphActionHandler("wilson", myhandler) AddComponentAction("SCENE", "pickable", function(inst, doer, actions, right)	if doer.prefab == "wilson" then -- tags also apply		table.insert(actions, GLOBAL.ACTIONS.CUSTOMPICK)	endend)

The actions table for Wilson ends up being PICK and CUSTOMPICK, so I need to give priority to CUSTOMPICK.

I can attach several functions via AddComponentAction that will be ran and may insert or not an action into the table.

 

Or remove, that is, for example

AddComponentAction("SCENE", "pickable", function(inst, doer, actions, right)	if doer.prefab == "wilson" then		for k, v in pairs(actions) do			actions[k] = nil		end	endend)

Now Wilson can't pick.

Link to comment
Share on other sites

Back again, I have reason to believe an outdated version of my quickpick code was causing client crashes when poison birchnut tree's were around.

 

I'm not exactly quite sure why, but the log.txt files were pointing to my characters with modified actions, and the line 

[00:43:58]: ERROR: Mod component actions are out of sync for mod workshop-390507921. This is likely a result of your mod's calls to AddComponentAction not happening on both the server and the client.
 
So I came here to use the code mentioned from Kzisor #6 (or DarkXero #7) to see if the problem goes away, since originally I wasn't using AddComponentAction, I was only appending PICK. The quickpick works normally under most circumstances, but once a poison birchtree appears, clients start crashing.
 
Does anybody know why specifically the poison birchtree's are causing this issue and nothing else?  I already tested without the character mods and I know it doesn't happen otherwise, so I'm just presuming it's because I'm using outdated code.
Link to comment
Share on other sites

@Kzisor, Yes I figured that much, but the thing that has my confused is I'm trying to figure out where that pertains to the mod's I'm using.

 

This is the only code in my character mod that does anything with actions.

 

Edit: While looking at it, I think I might have noticed the problem.  I think I might have copied things wrong.

 

This really bug's me, I look at the code several times and never notice anything amiss, then I post the code on the problem and immediately notice a problem.  Why is it that I overlook things until I press that submit button?  It will be a mystery to me I guess.

 

I'll be back if my problem still exists.

 

Edit 2: Okay using the correct code, but still having the crash

This is the code I'm using.

local myhandler = function(sg)	local old = sg.actionhandlers[GLOBAL.ACTIONS.PICK].deststate	sg.actionhandlers[GLOBAL.ACTIONS.PICK].deststate = function(inst, action)		if action.target.components.pickable then			if action.target.components.pickable.quickpick or inst:HasTag("quickpicker") then				return "doshortaction"			end			return old(inst, action)		end	endendAddStategraphPostInit("wilson",myhandler)

And this is the crash that's happening

[00:43:58]: [string "scripts/componentactions.lua"]:916: attempt to index field '?' (a nil value)LUA ERROR stack traceback:scripts/componentactions.lua:916 in (method) CollectActions (Lua) <898-930>   self (valid:true) =      GUID = 101555      Transform = Transform (0DE00498)      inlimbo = false      actionreplica = table: 2060C130      event_listening = table: 2060C590      actioncomponents = table: 2060D878      lower_components_shadow = table: 2060B938      entity = Entity (27CD1268)      AnimState = AnimState (0DE06558)      prefab = deciduoustree      build = normal      Network = Network (0DE018F8)      persists = true      MiniMapEntity = MiniMapEntity (0DE01AF8)      event_listeners = table: 2060C428      modactioncomponents = table: 167C7368      dragonflypriority = 1      spawntime = 58.600003056228      name = Birchnut Tree      replica = table: 2060B988      Physics = Physics (0DE03138)      components = table: 2060B910      SoundEmitter = SoundEmitter (0DE04CB8)   type = SCENE   arg = nil   t = table: 16AF2540   modname = workshop-390507921   modtable = table: 167CCF98

Since the code I listed is the ONLY THING I know of that really does anything involving actions, it's the only culprit I can thing of.

 

 

Edit 3: The crash happens when a client put's their mouse over a Poison Birch Tree while it's alive.

 

Edit 4: I think I fixed the problem. I put this under the code I was using

AddComponentAction("SCENE", "pickable", function(inst, doer, actions, right)    table.insert(actions, GLOBAL.ACTIONS.PICK)end)
Edited by Zackreaver
Link to comment
Share on other sites

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
 Share

×
  • Create New...