Forum

> > CS2D > Scripts > Pull a Player
Forums overviewCS2D overview Scripts overviewLog in to reply

English Pull a Player

14 replies
To the start Previous 1 Next To the start

old Pull a Player

Mami Tomoe
User Off Offline

Quote
Hello!

I'm requesting assistance in the creation of a function which will do the following:

us Pull a player to the given X and Y coordinates. us

1
2
3
function pull(p, x, y, force)
	-- magic(?)
end

• The code should be as efficient as possible , since I'm going to call it often (at least every second) .

• Also, a player shouldn't be pulled through a wall unless
force
is set to true.

Thanks

old Re: Pull a Player

Dousea
User Off Offline

Quote
1
2
3
4
5
6
7
8
local floor = math.floor
local setpos = 'setpos %d %d %d'

function pull(p, x, y, force)
	if not tile(floor(x/32), floor(y/32), 'wall') or force then
		parse(setpos:format(p, x, y))
	end
end

old Re: Pull a Player

Mami Tomoe
User Off Offline

Quote
I meant that you would be able to use this in order to pull a player (p) to another player (x, y), but not instantly.

Maybe a "strength" parameter is required, though I don't mind if it's static (4 pixels are fine).

old Re: Pull a Player

Quattro
GAME BANNED Off Offline

Quote
You have to use lerp. Or if you want to make it run real fast, use bressenham's algorithm.

I'd make it using a function which moves a player a bit towards the target and runs itself with a timer which will be a way to control speed and stops when it either reaches the other player or bumps into a wall.

old Re: Pull a Player

Bowlinghead
User Off Offline

Quote
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function move(id,start_x,start_y,amount_loop,speed,distance_x,distance_y,wallcheck)
     if start_x==0 then start_x= player(id,"x") end
     if start_y==0 then start_y= player(id,"y") end
     timer(speed,"parse",'lua "parameter('..id..','..start_x..','..start_y..','..amount_loop..','..speed..','..distance_x..','..distance_y..','..wallcheck..')"',amount_loop)
end
function parameter(id,start_x,start_y,amount_loop,speed,distance_x,distance_y,wallcheck)
     if counter==nil then counter=0 end
     if counter>=amount_loop then counter=0 end
     if wallcheck==nil or wallcheck<0 then wallcheck=0 end
     if wallcheck>=1 then 
          start_x = start_x + (counter*distance_x)
          start_y = start_y + (counter*distance_y)
          extra_x = player(id,"tilex")
          extra_y = player(id,"tiley")
          if tile(extra_x,extra_y,"walkable")==true then
               counter = counter + 1
               parse("setpos "..id.." "..start_x.." "..start_y)
               speed=speed+speed
          end
     elseif wallcheck==0 then
          counter = counter + 1
          start_x = start_x + (counter*distance_x)
          start_y = start_y + (counter*distance_y)
          parse("setpos "..id.." "..start_x.." "..start_y)
          speed=speed+speed
     end
end

file cs2d Skriptbasierte Bewegungen has written
Parameters:
id = Player-Id
start_x = the start position of the player in pixels (0 means the actual player position.)
start_y = the start position of the player in pixels (0 means the actual player position)
speed = in which time distance does the player move in miliseconds? (lower values means a faster and more liquid motion)
distance_x = how much pixels (x) does the player move every "speed"-miliseconds?
distance_y = how much pixels (y) does the player move every "speed"-miliseconds?
amount_loop = how often does the player moves? (higher values means that the animation needs more time)
wallcheck = set to 1 if the player should stop if he is touching a wall. Set to 0 if the player can clip through the wall.


Now we just need a giant fist grabbing the player to his destination
edited 1×, last 08.11.19 08:40:39 pm

old Re: Pull a Player

Dousea
User Off Offline

Quote
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
-- t = the elapsed time
-- b = begin
-- c = change (ending-beginning)
-- d = duration
local function inquad(t, b, c, d)
    t = t / d
    return c * (t*t) + b
end

local floor = math.floor
local parameter = 'lua "_pull%(%d,%d,%d,%d,%d,%d,%s%)'
local setpos = 'setpos %d %d %d'
local time = {} -- to determine of the elapsed time

function _pull(i, sx, sy, ex, ey, d, f)
    time[i] = time[i] + 1
    
    local x = inquad(time[i], sx, ex-sx, d)
    local y = inquad(time[i], sy, ey-sy, d)
    
    if not tile(floor(x/32), floor(y/32), 'walkable') or force then
        parse(setpos:format(i, x, y))
    end
end

-- id       = player ID
-- x, y     = to what position does it pull
-- duration = the duration of the pull (in seconds)
-- force    = penetrate through walls?
function pull(id, x, y, duration, force)
    if not time[id] or time[id] > 0 then
        time[id] = 0
    end

    local param = parameter:format(id,
                                   -- i assume that player coordinates are not
                                   -- integers
                                   floor(player(id, 'x')),
                                   floor(player(id, 'y')),
                                   x, y,
                                   duration,
                                   force)
    
    timer(1000, 'parse', param, duration)
end
I'm following user Quattro's suggestions and user Bowlinghead's code. I don't test it though, I'm sorry.

old Re: Pull a Player

Mami Tomoe
User Off Offline

Quote
I don't think it works, is there a simple way to just pull a player towards X, Y?

Like:
pull(p, x, y, pixels, force)


Also I have a special timer function that does this:

Timer(duration, function() end, count)


So assume I'm going to use it if needed.

old Re: Pull a Player

Bowlinghead
User Off Offline

Quote
What about telling us more about your timer function?

I mean we gave you a full code but apparently you didnt even read through it.
1
2
3
4
5
6
-- id       = player ID
-- x, y     = to what position does it pull
-- duration = the duration of the pull (in seconds)
-- force    = penetrate through walls?
function pull(id, x, y, duration, force)
(...)

Actually to pull a player you miss a parameter which is the duration, or in other words how fast you pull the people. Or what is your definiton of force?

Whats the matter? When the code doesnt work you should at least give the red console error to us and mark the line.
user Dousea has written
I don't test it though, I'm sorry.

Me neither
edited 1×, last 09.11.19 07:46:23 pm

old Re: Pull a Player

Mami Tomoe
User Off Offline

Quote
There's no error, the player I'm trying to pull just disappears and I don't know where he goes because I have many bots.

old Re: Pull a Player

Bowlinghead
User Off Offline

Quote
You can run 2 clients on the same windows PC for that matters.

And also you could use print, dont you.

old Re: Pull a Player

Mami Tomoe
User Off Offline

Quote
I don't think using 3 functions just makes sense, it would be much faster and easier to remake this.


What I give:

victim_id - int
goal_x - int
goal_y - int
strength_in_pixels - int
should_skip_walls - boolean

old Re: Pull a Player

Bowlinghead
User Off Offline

Quote
Instructions unclear about strength in pixels;
so target will almost never hit the goal coords unless strength = sqrt(dx² + dy²)?

old Re: Pull a Player

Dousea
User Off Offline

Quote
Probably the error is in the string formatting at line 22, my bad. Well what you want is clearly linear movement towards the specified coordinates, not with easing function like I did with in quad, which gives a more pull-like movement.
1
2
3
4
5
6
7
8
9
10
11
12
13
function pull(id, x, y, speed, force)
    local px, py = player(id, 'x'), player(id, 'y')
    local a = math.atan2(x-px, py-y) -- angle from player to x,y
    local nx = px + speed * math.cos(a)
    local ny = py + speed * math.sin(a)
    
    if not tile(math.floor(nx/32), math.floor(ny/32), 'walkable') or force then
        parse('setpos ' .. id .. ' ' .. nx .. ' ' .. ny)
        return true
    end
    
    return false
end
It would return true if it successfully pulls the player, false if otherwise. It doesn't check whether the player have arrived to the destination or not.

You can't use a timer if you don't specify the duration of the pull, so you need to call the function as you see it fits (like every second). Well you can use a timer however you need to gain the length of player to specified coordinates and divide it with the speed, and with another kind of logic which is tiresome.

old Re: Pull a Player

Quattro
GAME BANNED Off Offline

Quote
This is bare bones, you can improve this by letting the player be pulled alongside wall^^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
----------------------
--Setup vars----------
----------------------
function array(size, value)
	local array = {}
	for i = 1, size do
		array[i] = value
	end
	return array
end
player_pull = array(32, false)

----------------------
--Functions-----------
----------------------
function wordSplit(input, separator)
    if separator == nil then
        separator = "%s"
	end
    local t = {} ; i = 1
    for str in string.gmatch(input, "([^"..separator.."]+)") do
        t[i] = str
        i = i + 1
	end
    return t
end
function pull(infostring) --infostring: {id targetlocationX targetlocationY speed force} lower speed = faster

	local sensitivity = 2 --pixels to move each check. increasing this adds performance and makes the pull choppy.
	local wall_distance = 16 --pixels to stop before getting sucked into a wall

	--do not change these
	local var = wordSplit(infostring)
	local id = tonumber(var[1])
	local x = tonumber(var[2])
	local y = tonumber(var[3])
	local speed = tonumber(var[4])
	local force = var[5]
	local px, py = player(id, 'x'), player(id, 'y')
	local vectorX = x - px
	local vectorY = y - py
	local magnitude = math.sqrt(vectorX^2 + vectorY^2)
	local dirX = vectorX / magnitude
	local dirY = vectorY / magnitude
	local targetX = px + dirX * sensitivity
	local targetY = py + dirY * sensitivity
	local checkX = px + dirX * wall_distance
	local checkY = py + dirY * wall_distance

	if magnitude < wall_distance or not player_pull[id] then
		return
	end

	if force == '1' then
		parse('setpos ' .. id .. ' ' .. targetX .. ' ' .. targetY)
		timer(speed, 'pull', id..' '..x..' '..y..' '..speed..' '..force, 1)
	else
		if tile(math.floor(checkX / 32), math.floor(checkY / 32), 'walkable') then
			parse('setpos ' .. id .. ' ' .. targetX .. ' ' .. targetY)
			timer(speed, 'pull', id..' '..x..' '..y..' '..speed..' '..force, 1)
			return
		else
			timer(speed, 'pull', id..' '..x..' '..y..' '..speed..' '..force, 1)
			return
		end
	end
end

----------------------
--Hook Functions------
----------------------
function serveraction(id, action)
	if action == 1 then
		if not player_pull[id] then
			player_pull[id] = true
			pull(id..' 0 0 25 0')
		else
			player_pull[id] = false
		end
	end
end

----------------------
--Hooks---------------
----------------------
addhook('serveraction', 'serveraction')
To the start Previous 1 Next To the start
Log in to reply Scripts overviewCS2D overviewForums overview