Raised This Month: $51 Target: $400
 12% 

[L4D] How to count the distance in map route?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 11-23-2018 , 04:16   [L4D] How to count the distance in map route?
Reply With Quote #1

Hi,

if you played L4D, you know the map has a route. It is not a direct line between 2 safe rooms.
It can be route in the form of a maze or snake... I need to count distance how far has the player gone from safe room (counting by route line). Any property for this?

Thank you.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]
Dragokas is offline
Mr. Zero
Veteran Member
Join Date: Jun 2009
Location: Denmark
Old 11-23-2018 , 05:00   Re: [L4D] How to count the distance in map route?
Reply With Quote #2

The map distance concept within L4D is called "Map Flow". The Director uses it to figure out how far the Survivors have progressed and when to spawn Bosses (Tank and Witch).

ProdigySim made some very nice stocks for this some years back.

https://forums.alliedmods.net/showthread.php?t=180028

The specific function you are looking for is called:

PHP Code:
stock float L4D2Direct_GetMapMaxFlowDistance(); 
This function returns map length, A to B in Survivor movement, in hammer units. An example would be No Mercy map 1 is 8000 units.

Then you can use
PHP Code:
stock float L4D2Direct_GetFlowDistance(int Client); 
to get the Survivors individual flow count. Might return something like
PHP Code:
4000.0 
That means the Survivor is half way through the map.

Beaware, sometimes the Survivor can not be pinpointed or get outside of the flow of the map (map exploits or whatever). Which can make the return flow value be weird (honestly it may return any value, the Director attempts to guess where the Survivor may be). Personally I find using a delta timer function with a median value (just store the last three flow values of the Survivor and get the median value) to work well against this problem.

Furthermore if Survivors can move in the opposite direction of the checkpoint safe room from their starting location (in other words, they can move backwards which puts them further away from the checkpoint), the flow value can reach negative values. It doesn't mean it is invalid, it just means Survivors are getting further away from the checkpoint.
The map max flow distance is counted from starting checkpoint to end checkpoint, but it doesn't mean a Survivor can move behind or past the checkpoints (so Survivors can reach higher flow values than the map max flow distance returns and they can reach negative values as well). Be sure to validate your inputs!

And lastly, areas only Infected are suppose to reach returns the following value for Survivors; (Areas marked as INFECTED_ONLY with the Nav Editor)
PHP Code:
#define FLOW_VALUE_INFECTED_ONLY_AREA -9999.000000 
Oh and here is a small stock function to return flow from a point without a client:
PHP Code:
stock bool GetFlowFromPoint(float point[3], &float flow)
{
    
Address terrorNavPointer L4D2Direct_GetTerrorNavArea(point);
    if (
terrorNavPointer == Address_Null)
    {
        return 
false;
    }
    
    
flow L4D2Direct_GetTerrorNavAreaFlow(terrorNavPointer);
    return 
true;

I hope it could be of some use
Mr. Zero is offline
spumer
Senior Member
Join Date: Aug 2011
Old 11-23-2018 , 05:42   Re: [L4D] How to count the distance in map route?
Reply With Quote #3

I'm use Left4Fix natives to flow control. It's more stable than L4D2Direct_GetFlowDistance

Example
https://github.com/spumer/Left4Fix/b...ft4fix_test.sp
__________________
spumer is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 11-23-2018 , 05:42   Re: [L4D] How to count the distance in map route?
Reply With Quote #4

wow, very appreciate for detailed response. I would never have guessed what is mean "flow"
Quote:
The map max flow distance is counted from starting checkpoint to end checkpoint, but it doesn't mean a Survivor can move behind or past the checkpoints (so Survivors can reach higher flow values than the map max flow distance returns and they can reach negative values as well).
So, does it mean clients flow is never decreased? So, client flow is not a distance to safe room, but a number of client's steps regardless of the direction of movement?

If so, maybe better to get client's origin and use GetFlowFromPoint() stock?

Quote:
Personally I find using a delta timer function with a median value (just store the last three flow values of the Survivor and get the median value) to work well against this problem.
It's a good idea. However, what arithmetics do you use to exclude wrong number from median? Like, if you have 1000, 1100, -5000. Or: 1000, 9999, 1100.

Thank you.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]
Dragokas is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 11-23-2018 , 05:48   Re: [L4D] How to count the distance in map route?
Reply With Quote #5

spumer, thank you too! Always good to have alternatives.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]
Dragokas is offline
Mrs cheng
Member
Join Date: Mar 2017
Old 11-23-2018 , 06:07   Re: [L4D] How to count the distance in map route?
Reply With Quote #6

The following is an introduction to the script, I hope to help you.


float GetCurrentFlowDistanceForPlayer(CTerrorPlayer player)
Returns the navigation flow distance from the start to the specified player.

float GetCurrentFlowPercentForPlayer(CTerrorPlayer player)
Returns how far in the navigation flow from the start to the end the player is.

float GetFlowDistanceForPosition(Vector position)
Returns the navigation flow distance from the start to the specified point.

float GetCurrentFlowPercentForPosition(Vector position, bool unknown)
Returns how far in the navigation flow from the start to the end the position is.

float GetMaxFlowDistance()
Returns the navigation flow distance from the start to the end of the level.

float GetAverageSurvivorFlowDistance()
Returns the navigation flow distance from the start to the survivors position averaged.
Mrs cheng is offline
Skyy
AlliedModders Donor
Join Date: Jan 2010
Location: Toronto, Canada
Old 11-23-2018 , 06:38   Re: [L4D] How to count the distance in map route?
Reply With Quote #7

Left 4 Downtown 0.5.7 also supports grabbing map flow, but returns it as 0.0 - 1.0
Skyy is offline
Mr. Zero
Veteran Member
Join Date: Jun 2009
Location: Denmark
Old 11-24-2018 , 14:42   Re: [L4D] How to count the distance in map route?
Reply With Quote #8

Quote:
Originally Posted by Dragokas View Post
wow, very appreciate for detailed response. I would never have guessed what is mean "flow"

So, does it mean clients flow is never decreased? So, client flow is not a distance to safe room, but a number of client's steps regardless of the direction of movement?

If so, maybe better to get client's origin and use GetFlowFromPoint() stock?
The client flow can go up and down. It is not number of steps but their distance from starting or ending checkpoint (depending on how you interpret the result). An example:

Code:
Map Max Flow Distance: 12000

Survivor1 Flow Value: 4000.0
Survivor2 Flow Value: -200.0
Survivor3 Flow Value: -9999.0
Survivor4 Flow Value: 11000.0

Survivor 1 is a third through the map or 4000 hammer units away (in First Person mode, e.g. not birds eye viewpoint).
Survivor 2 is 200 hammer units away from the starting checkpoint and 12200 hammer units away from the ending checkpoint.
Survivor 3 is in an Infected only area, which may be where ever in the map.
Survivor 4 is only 1000 hammer units away from the ending checkpoint and 11000 hammer units away from the starting checkpoint.

Quote:
Originally Posted by Dragokas View Post
It's a good idea. However, what arithmetics do you use to exclude wrong number from median? Like, if you have 1000, 1100, -5000. Or: 1000, 9999, 1100.
Well that the thing, there is only one "wrong" number. Which is -9999.0 (INFECTED_ONLY). By default Survivors should not be able to reach Infected Only areas, but custom maps or incorrectly nav'd areas may allow Survivors to reach those areas.

So in your example the Survivor could have been teleported, respawned (defib or plugins) or noclip'd. It would be up to you to detect when the incoming flow value is valid or not. For example in my plugin I always make sure the Client movetype is never noclip, otherwise ignore flow value (and clear delta if they recently exit noclip mode).

Also with median results would looks like this:
Code:
Input:
1000, 1100, -5000
Ranked:
-5000, 1000, 1100
Median Output:
1000

Input:
1000, 9999, 1100
Ranked:
1000, 1100, 9999
Median Output:
1100
That is why, I find personally, the median works when Survivors can move back and forth in flow map. Another example
Code:
Input: 
254.6, 248.5, 253.8
Ranked:
248.5, 253.8, 254.6
Median Output:
253.8
And of course it also depends on what you need the flow value for and how often it needs to be updated, you may need more than three inputs for your requirements.

As said, Survivors may get out of the map through map exploits or noclip (admins flying into the sky to observe areas with trouble some players or whatever) which has just 'garbage' flow values. No real solution for other than just verify that Survivor is not currently noclipping or flying (a Tank punched Survivor in the air or off a cliff).

Hopefully I weren't too obtuse, been a while since I worked with the Director flow maps
Mr. Zero is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 19:28.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode