Jump to content

Way to disable all actions except moving?


Recommended Posts

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

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 :wilson_flower:!!

Link to comment
Share on other sites

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 by ZupaleX
Link to comment
Share on other sites

I tried to do it, but I get this crash 1.png

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

 

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 by ZupaleX
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

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 :wilson_smile:!! 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 :wilson_dorky:?

 

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 :wilson_flower:!!

Link to comment
Share on other sites

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 by ZupaleX
Link to comment
Share on other sites

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 :wilson_dorky:!

And thanks again for your help man :wilson_flower:!!!

Link to comment
Share on other sites

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

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