Jump to content

[HELP] Character sliding when using locomotor on server-side


Recommended Posts

I'm trying to give my character an ability that triggers when the X key is pressed (because there are already too many actions tbh and this ability doesn't use an item, it's just always there passively), targeting whatever the mouse is over. The ability in this case is the ability to haunt things.

She's supposed to walk towards the target if not in range, just like normal actions.

It works perfectly on host but on server she will be delayed for a bit, then teleport in the direction she's supposed to be walking and then start sliding towards her destination. I tried making the client just play the run animation at the start but it doesn't fix the initial teleporting issue. Trying to change her state to run or run_start or anything doesn't work either.

I've spent a good two days just digging through the files for playercontroller, locomotor, actions, etc. trying just about every change I can think of and it seems like I can't get anything to work, I can only ever get halfway.

Whenever I try running the locomotor on only the client, I can't get the action to proc at the end. If I try running the locomotor on both client and server, the action instantly fails on the server if she's not already in range to use the ability. If I set act as the action for bufferedaction instead of using ACTIONS.WALKTO, it doesn't run when she reaches her destination.

ModMain.lua:

Spoiler

-- haunt; the serverside code for receiving the RPC
local function YuyuHaunt(player, x, y, z)
	if player.prefab == "yuyuko" and not player.sg:HasStateTag("busy") and not player.sg:HasStateTag("sleeping") then
		local ents = TheSim:FindEntities(x, y, z, 5)
		if ents then 
			for i, target in ipairs(ents) do
				print(target.name)
				if target ~= player then
					player:haunt(target)
					return 
				end
			end
			--print("no ents found on server")
		end
	else
		--print("Not Yuyuko, or was busy / sleeping.")
	end
end	

-- Add RPC
AddModRPCHandler("yuyuko_rpc", "YuyuHaunt", YuyuHaunt)

-- The keypress (x for now)
GLOBAL.TheInput:AddKeyDownHandler(120, function()
	local player = GLOBAL.ThePlayer
	if player and not player.HUD:IsChatInputScreenOpen() and not player.HUD:IsConsoleScreenOpen() and IsDefaultScreen() then
		if player.prefab == "yuyuko" then
			local target = GLOBAL.TheInput:GetWorldEntityUnderMouse()
			if target  and target ~= player then
				if not GLOBAL.TheWorld.ismastersim then 		
					local x, y, z = target.Transform:GetWorldPosition()
					SendModRPCToServer(MOD_RPC["yuyuko_rpc"]["YuyuHaunt"], x, y, z)
				else
					--host code; will do this when client/server code is fixed.
				end
			end
		end
	end
end)

 

yuyuko.lua:

Spoiler

--The code for haunting
local function haunt(inst, target)
	if inst.prefab == "yuyuko" then
		local act = ACTIONS.HAUNT
		act.doer = inst
		act.target = target
		act.ghost_exclusive = false
		local function haunt_do() 
			print("trying")
			inst.sg:GoToState("give")
			inst:DoTaskInTime(0.4, function()
				if act.rangecheckfn(inst, target) then 
					act.fn(act)
				else
					print("too far for act.fn")
				end
			end)
		end
		local buffaction = BufferedAction(inst, target, ACTIONS.WALKTO)
		buffaction.distance = 3
		buffaction:AddSuccessAction(haunt_do)
		buffaction:AddFailAction(function () print("Failed") end)
		
		inst.components.playercontroller.locomotor:GoToEntity(target, buffaction, false)
	end
end

 

 

This is what happens: http://i.imgur.com/JuQ1KUV.gifv

Edited by code4240
Link to comment
Share on other sites

EDIT: nothing I read too fast. This kind of issue is usually quite unerving. I'll take a closer look at it later if I can be of any help.

Could you post more though? Like, everything which is connected to what you want to achieve?

Edited by ZupaleX
Link to comment
Share on other sites

Sorry for double post but decided it will be better for clarity sake

This worked for me. I obviously removed the part which were referring to your character since I don't have it.

Oh and I removed the function IsDefaultScreen() because you defined it locally but did not post it.

It display the message "I cannot do that" because I just hacked that together in 10 minutes using the HAUNT action so it is probably due to the fact that the HAUNT is intended to be used by a ghost but other than that the host AND client moves to the target before making it "haunted".

You can probably change a few stuffs to make it look more elegant but this is functional.

Spoiler

local ACTIONS = GLOBAL.ACTIONS

local MYHAUNT = GLOBAL.Action({ rmb=false, mindistance=2, ghost_valid=true, canforce=true, rangecheckfn=DefaultRangeCheck })
MYHAUNT.str = "MYHAUNT"
MYHAUNT.id = "MYHAUNT"
MYHAUNT.fn = function(act)
	print("ouuuuuuuh")
	ACTIONS.HAUNT.fn(act)
end

AddAction(MYHAUNT)

AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.MYHAUNT))
AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.MYHAUNT))

-- haunt; the serverside code for receiving the RPC
local function YuyuHaunt(player, x, y, z)
	if not player.sg:HasStateTag("busy") and not player.sg:HasStateTag("sleeping") then
		local ents = GLOBAL.TheSim:FindEntities(x, y, z, 1)
		if ents then 
			for i, target in ipairs(ents) do
				print(target.name)
				if target ~= player and player.components and player.components.locomotor then
					local buffAction = GLOBAL.BufferedAction(player, target, ACTIONS.MYHAUNT)
					player.components.locomotor:PushAction(buffAction)
					return 
				end
			end
		end	--print("no ents found on server")
	end
end	

-- Add RPC
AddModRPCHandler("yuyuko_rpc", "YuyuHaunt", YuyuHaunt)

-- 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 target = GLOBAL.TheInput:GetWorldEntityUnderMouse()
		if target  and target ~= player then
			local x, y, z = target.Transform:GetWorldPosition()
		
			local buffAction = GLOBAL.BufferedAction(player, target, ACTIONS.MYHAUNT)
		
			if not GLOBAL.TheWorld.ismastersim then 	
				buffAction.preview_cb = function()
					SendModRPCToServer(MOD_RPC["yuyuko_rpc"]["YuyuHaunt"], x, y, z)
				end
				player.components.locomotor:PreviewAction(buffAction, true)
			else
				YuyuHaunt(player, x, y, z)
				--host code; will do this when client/server code is fixed.
			end
		end
	end
end)

 

 

Edited by ZupaleX
Link to comment
Share on other sites

Thanks! Besides the "I can't do that" thing it pretty much works. (I had to add the give state to it but that pretty much worked)

Strangely, she didn't say "I can' do that" in my original code, and the fn for haunt doesn't have any reference to the line, so I'm not sure where that's happening.

Link to comment
Share on other sites

On second thought, it seems that using the give state triggers a stack overflow error originating in preview_cb if I use the ability a couple times. I am slightly dumbfounded by this.

EDIT: just replacing the state entry with animation calls seems to fix the issue.

Also, console has confirmed to me that the bufferedAction is calling both its success actions and its fail actions when I use it, which is probably what's triggering the "I can't do that" thing even though the ability works.

EDIT2: The fix for her saying "I can't do that" is just to make the new action's fn return true.

EDIT3: Ignore what I said about the animations and states. The actual solution is just to do this:

AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(ACTIONS.MYHAUNT, "give"))
AddStategraphActionHandler("wilson_client", GLOBAL.ActionHandler(ACTIONS.MYHAUNT, "give"))

-telling it to add that action handler to the "give" state makes it work perfectly.

Edited by code4240
Link to comment
Share on other sites

Hi,

glad you got it sorted out.

Sorry about the return true which was missing I don't know how I missed that.

For the destination state for the AddStategraphActionHandler, at first I put "doshortaction" and did my initial testing on that. It worked ok even when performing the action several times in a row but decided that maybe you don't want a generic animation and just remove the deststate completely. As far as I saw in the stategraph.lua, if the deststate is missing it sends to a default function which just performs the action immediately when available and do not display anything. I tested it again quickly, like using the action once or twice, and did not get an error so I assume it would be fine ^^. But I guess it's more complicated than that. The most elegant way would be to write your own state :) (but "give" or "doshortaction" would do just fine if you did not have a specific wish for the animation played when performing your action).

Link to comment
Share on other sites

55 minutes ago, ZupaleX said:

The most elegant way would be to write your own state :) (but "give" or "doshortaction" would do just fine if you did not have a specific wish for the animation played when performing your action).

Well, only real reason for me to make a custom state for this would be if I had a custom animation, which I don't. The actual executed code is pretty simple.

Course, if you think there's an animation that fits better than give/standingaction, I'm open for suggestions..

Link to comment
Share on other sites

5 hours ago, code4240 said:

Well, only real reason for me to make a custom state for this would be if I had a custom animation, which I don't. The actual executed code is pretty simple.

Course, if you think there's an animation that fits better than give/standingaction, I'm open for suggestions..

Make your own :p

Just joking, but I would maybe use the "doshortaction" which is the animation use to plant things or put stuffs in the fire, instead of the "give" one? I guess it would match better for small objects? But that's just a detail

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