ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 You have some buttons which modify the way the other buttons react. Like CONTROL with the attack button create a force attack while the attack action is not available otherwise. You have a force inspect button as well, etc... The part about the actionbuttonoverride is to say that if such a button is pressed at the same time than the space bar, then it should perform the action linked to that combination of buttons instead. For the force attack you will have to override the function somewhere in playeractionpicker and/or playercontroller which is executed when the CONTROL_FORCE_ATTACK button is pressed (you can see the 4 controls modifiers in playercontroller.lua). I did not look too much into the details but that's where it will be. I am a bit puzzled by your code though. You are not linking any State in the AddStategraphActionHandler? Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 8 hours ago, ZupaleX said: I am a bit puzzled by your code though. You are not linking any State in the AddStategraphActionHandler? I don't do this because my state is played by a local function with some if checks, if the state just plays then it doesn't have those if checks to not play the jump under certain circumstances, I think. Also, after lots of playing around with this code for my action Spoiler local JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) JUMP_ADAM.strfn = function(act) return "Jump" end JUMP_ADAM.id = "JUMP_ADAM" JUMP_ADAM.fn = function(act) jump(act) return true end local RUN_JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) RUN_JUMP_ADAM.strfn = function(act) return "Run Jump" end RUN_JUMP_ADAM.id = "RUN_JUMP_ADAM" RUN_JUMP_ADAM.fn = function(act) run_jump(act) return true end AddAction(JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.JUMP_ADAM)) AddAction(RUN_JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) local function NewGetActionButtonAction(self, force_target) RemovePlayerActions(self.inst, true) RemovePlayerActions(self.inst, false) if (not self.ismastersim and (self.remote_controls[CONTROL_ACTION] or 0) > 0) or not self:IsEnabled() or (force_target ~= nil and (not force_target.entity:IsVisible() or force_target:HasTag("INLIMBO") or force_target:HasTag("NOCLICK"))) then return elseif self.inst.components.locomotor:WantsToMoveForward() then return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.RUN_JUMP_ADAM) else return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.JUMP_ADAM) end end AddComponentPostInit("playercontroller", function(controller) local OriginalGetActionButtonAction = controller.GetActionButtonAction controller.GetActionButtonAction = function(self, force_target) local buffAction = NewGetActionButtonAction(self, force_target) if buffAction ~= nil then return buffAction end return OriginalGetActionButtonAction(self, force_target) end end) I feel like space is a bad option for my jump since it completely removes the ability to do anything with space other than jump. And lots of stuff like closing/opening wood gates, putting out smoldering objects, & picking up multiple items is very hard to do without space.. So, I was wondering if there's a way I can make it activate the action by a certain button? Like maybe the R button on keyboard? I tried replacing self.remote_controls[CONTROL_ACTION] with self.remote_controls[R] but it didn't effect anything because I probably did it the wrong way? So, if that's not possible I had another idea the action be activated with TAKE HALF action when the cursor is not on an item to take half of? I think that would also be better since the button would be customizable in controls, but I don't know which one be harder to do or maybe both impossible to do? And again I must say thank you ZupaleX !! Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 (edited) You can map keys to function, I just don't remember how exactly. I'll check it out a bit later. EDIT: @SuperDavid I invite you to look at this thread for mapping custom functions to a key, the answer I provided there is functional. Edited July 21, 2017 by ZupaleX Link to comment Share on other sites More sharing options...
. . . Posted July 21, 2017 Author Share Posted July 21, 2017 I tried to do it, but I get this crash Spoiler local JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) JUMP_ADAM.strfn = function(act) return "Jump" end JUMP_ADAM.id = "JUMP_ADAM" JUMP_ADAM.fn = function(act) jump(act) return true end local RUN_JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) RUN_JUMP_ADAM.strfn = function(act) return "Run Jump" end RUN_JUMP_ADAM.id = "RUN_JUMP_ADAM" RUN_JUMP_ADAM.fn = function(act) run_jump(act) return true end AddAction(JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.JUMP_ADAM)) AddAction(RUN_JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) local function NewGetActionButtonAction(self, force_target) RemovePlayerActions(self.inst, true) RemovePlayerActions(self.inst, false) if (not self.ismastersim and (self.remote_controls[CONTROL_ACTION] or 0) > 0) or not self:IsEnabled() or (force_target ~= nil and (not force_target.entity:IsVisible() or force_target:HasTag("INLIMBO") or force_target:HasTag("NOCLICK"))) then return elseif self.inst.components.locomotor:WantsToMoveForward() then return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.RUN_JUMP_ADAM) else return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.JUMP_ADAM) end end AddComponentPostInit("playercontroller", function(controller) local OriginalGetActionButtonAction = controller.GetActionButtonAction controller.GetActionButtonAction = function(self, force_target) local buffAction = NewGetActionButtonAction(self, force_target) if buffAction ~= nil then return buffAction end return OriginalGetActionButtonAction(self, force_target) end end) -- haunt; the serverside code for receiving the RPC local function Jump(player) if player.components.locomotor:WantsToMoveForward() then return GLOBAL.BufferedAction(player, nil, ACTIONS.RUN_JUMP_ADAM) else return GLOBAL.BufferedAction(player, nil, ACTIONS.JUMP_ADAM) end end -- Add RPC AddModRPCHandler("jump", "Jump", Jump) -- The keypress (x for now) GLOBAL.TheInput:AddKeyDownHandler(GLOBAL.KEY_X, function() local player = GLOBAL.ThePlayer if player and not player.HUD:IsChatInputScreenOpen() and not player.HUD:IsConsoleScreenOpen() then local buffAction = GLOBAL.BufferedAction(player, ACTIONS.JUMP_ADAM) if not GLOBAL.TheWorld.ismastersim then SendModRPCToServer(MOD_RPC["jump"]["Jump"]) else Jump(player) end end end) I probably did something wrong again, sorry Link to comment Share on other sites More sharing options...
ZupaleX Posted July 21, 2017 Share Posted July 21, 2017 (edited) BufferedAction = Class(function(self, doer, target, action, invobject, pos, recipe, distance, forced, rotation) self.doer = doer self.target = target self.initialtargetowner = target ~= nil and target.components.inventoryitem ~= nil and target.components.inventoryitem.owner or nil self.action = action self.invobject = invobject self.doerownsobject = doer ~= nil and invobject ~= nil and invobject.replica.inventoryitem ~= nil and invobject.replica.inventoryitem:IsHeldBy(doer) self.pos = pos self.rotation = rotation self.onsuccess = {} self.onfail = {} self.recipe = recipe self.options = {} self.distance = distance or action.distance self.forced = forced self.autoequipped = nil --true if invobject should've been auto-equipped self.skin = nil end) And you are doing in the AddKeyDownHandler local buffAction = GLOBAL.BufferedAction(player, ACTIONS.JUMP_ADAM) first argument is self and is hidden => OK Second argument is the doer, in your case "player" => OK Third argument is the target, in your case nil => Not OK, you passed the action. The fourth argument only is the action. So local buffAction = GLOBAL.BufferedAction(player, nil, ACTIONS.JUMP_ADAM) in the AddKeyDownHandler instead of what you currently have. That might not be the only issue, it's just the one I spotted immediately. Let me know if you encounter more problems. EDIT: it just occured to me that you could pass the stuff you want to jump over as the target, like that your character would first walk toward the obstacle and jump only when he/she reaches the proper range to do so. Edited July 21, 2017 by ZupaleX Link to comment Share on other sites More sharing options...
. . . Posted July 22, 2017 Author Share Posted July 22, 2017 Okay, I have this code atm Spoiler local function jump(act) if act.doer.HUD:IsChatInputScreenOpen() or act.doer.HUD:IsConsoleScreenOpen() then return end if act.doer.gelid_mode == true or act.doer.heavy_armor == true or act.doer.jumping == true or act.doer.components.rider:IsRiding() or act.doer.sg:HasStateTag("busy") or act.doer:IsCarefulWalking() then return end if act.doer.components.locomotor:WantsToMoveForward() then act.doer.sg:GoToState("run_jump") elseif not act.doer.components.locomotor:WantsToMoveForward() and act.doer:IsOnValidGround() then act.doer.sg:GoToState("jump") end end local function run_jump(act) if act.doer.gelid_mode == true or act.doer.heavy_armor == true then return end if not act.doer.sg:HasStateTag("busy") and not act.doer.components.rider:IsRiding() then act.doer.sg:GoToState("run_jump") end end local JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) JUMP_ADAM.strfn = function(act) return "Jump" end JUMP_ADAM.id = "JUMP_ADAM" JUMP_ADAM.fn = function(act) act.doer.jump = true jump(act) return true end local RUN_JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) RUN_JUMP_ADAM.strfn = function(act) return "Run Jump" end RUN_JUMP_ADAM.id = "RUN_JUMP_ADAM" RUN_JUMP_ADAM.fn = function(act) act.doer.jump = true run_jump(act) return true end AddAction(JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.JUMP_ADAM)) AddAction(RUN_JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) local function NewGetActionButtonAction(self, force_target) RemovePlayerActions(self.inst, true) RemovePlayerActions(self.inst, false) if (not self.ismastersim and (self.remote_controls[CONTROL_ACTION] or 0) > 0) or not self:IsEnabled() or (force_target ~= nil and (not force_target.entity:IsVisible() or force_target:HasTag("INLIMBO") or force_target:HasTag("NOCLICK"))) then return elseif self.inst.components.locomotor:WantsToMoveForward() then return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.RUN_JUMP_ADAM) else return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.JUMP_ADAM) end end AddComponentPostInit("playercontroller", function(controller) local OriginalGetActionButtonAction = controller.GetActionButtonAction controller.GetActionButtonAction = function(self, force_target) local buffAction = NewGetActionButtonAction(self, force_target) if buffAction ~= nil then return buffAction end return OriginalGetActionButtonAction(self, force_target) end end) -- haunt; the serverside code for receiving the RPC local function Jump(player) if player.components.locomotor:WantsToMoveForward() then return GLOBAL.BufferedAction(player, nil, ACTIONS.RUN_JUMP_ADAM) else return GLOBAL.BufferedAction(player, nil, ACTIONS.JUMP_ADAM) end end -- Add RPC AddModRPCHandler("jump", "Jump", Jump) -- The keypress (x for now) GLOBAL.TheInput:AddKeyDownHandler(GLOBAL.KEY_X, function() local player = GLOBAL.ThePlayer if player and not player.HUD:IsChatInputScreenOpen() and not player.HUD:IsConsoleScreenOpen() then local buffAction = GLOBAL.BufferedAction(player, nil, ACTIONS.JUMP_ADAM) -- I changed this to what you said if not GLOBAL.TheWorld.ismastersim then SendModRPCToServer(MOD_RPC["jump"]["Jump"]) else Jump(player) end end end) And it doesn't crash anymore, but pressing X does nothing. I'm sorry for being such an idiot & thanks for being very patient with me! Feel free to respond whenever you have the time, like in a couple days or something that's fine . Link to comment Share on other sites More sharing options...
ZupaleX Posted July 22, 2017 Share Posted July 22, 2017 Your function Jump(player) is returning a BufferedAction but is actually never using it. Read again the example in the other thread. You will notice that this BufferedAction is then used in something else to actually perform that action (which is just buffered otherwise, thus the name). (Hint: something called PushAction and PreviewAction) Link to comment Share on other sites More sharing options...
. . . Posted July 23, 2017 Author Share Posted July 23, 2017 Okay, thank you ZupaleX I have this code Spoiler local JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) JUMP_ADAM.strfn = function(act) return "Jump" end JUMP_ADAM.id = "JUMP_ADAM" JUMP_ADAM.fn = function(act) if act.doer.jump == true or act.doer:IsCarefulWalking() then return end act.doer.jump = true jump(act) return true end local RUN_JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) RUN_JUMP_ADAM.strfn = function(act) return "Run Jump" end RUN_JUMP_ADAM.id = "RUN_JUMP_ADAM" RUN_JUMP_ADAM.fn = function(act) if act.doer.jump == true or act.doer:IsCarefulWalking() then return end act.doer.jump = true run_jump(act) return true end AddAction(JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.JUMP_ADAM)) AddAction(RUN_JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) local function Jump(player) if player.jump == true or player:IsCarefulWalking() then return end if player.components.locomotor:WantsToMoveForward() then local buffAction = GLOBAL.BufferedAction(player, nil, ACTIONS.RUN_JUMP_ADAM) player.components.locomotor:PushAction(buffAction) else local buffAction = GLOBAL.BufferedAction(player, nil, ACTIONS.JUMP_ADAM) player.components.locomotor:PushAction(buffAction) end end AddModRPCHandler("jump", "Jump", Jump) GLOBAL.TheInput:AddKeyDownHandler(GLOBAL.KEY_X, function() local player = GLOBAL.ThePlayer if player.jump == true or player:IsCarefulWalking() then return end if player and not player.HUD:IsChatInputScreenOpen() and not player.HUD:IsConsoleScreenOpen() then local buffAction = GLOBAL.BufferedAction(player, nil, ACTIONS.JUMP_ADAM) if not GLOBAL.TheWorld.ismastersim then buffAction.preview_cb = function() SendModRPCToServer(MOD_RPC["jump"]["Jump"]) end player.components.locomotor:PreviewAction(buffAction, true) else Jump(player) end end end) & now pressing X makes the character preform jump action & since the jump is a legit action now it cancels any other actions like wanting to pick up an item which's awesome !! The only thing is I can still force attack, but for that I think I will just edit the attack state to return if it has my jumping value or something. Now the only thing left I really need to make this jump very good is instead of X I would like when the player presses "CONTROL_SPLITSTACK" (from constants.lua) for the RPC action to go off then every player could customize there own button for jumping kinda, so would you happen to know how I could do that ? Also, can I ask what does this code do/mean exactly? player.components.locomotor:PreviewAction(buffAction, true) And thank you so much for your help you really made my jump action so, so much better now that it's a real action, thank you a lot !! Link to comment Share on other sites More sharing options...
ZupaleX Posted July 23, 2017 Share Posted July 23, 2017 (edited) I will take a closer look at the force attack thingy. For customizing the command, why don't you put a config option in your modinfo.lua? List all the keys and let the player select the key he/she wants to use. PreviewAction is used client side. The actions are handled by the server, the client should not execute any code except displaying the animation. PreviewAction is that. It plays the animation but does not perform any other tasks. Edited July 23, 2017 by ZupaleX Link to comment Share on other sites More sharing options...
. . . Posted July 23, 2017 Author Share Posted July 23, 2017 3 hours ago, ZupaleX said: For customizing the command, why don't you put a config option in your modinfo.lua? List all the keys and let the player select the key he/she wants to use. I thought of that too, but the problem I think is only the owner of a world can change the config options meaning whatever button they set jump to will be that way for all players. But if it was a key to toggle the action is "CONTROL_SPLITSTACK" then everyone could have whatever key assigned to that action toggle the action, thus allowing everyone to have a unique button for doing a jump ! And thanks again for your help man !!! Link to comment Share on other sites More sharing options...
ZupaleX Posted July 23, 2017 Share Posted July 23, 2017 Hmmm, you're right. I don't know if there is a way to split the config file of a mod between a server side config and a client side config. What could work would be to put your RPC and the key handling in a separate mod which would be client side only so every client could specify the key they want to use. Then you need to load it before the actual server side mod which would do all the rest. But that seems like a lot of effort, there must be a smarter way to do that. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now