AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Code Snippets/Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=83)
-   -   Tutorial: Catching Weapons Fire in mod inspecific fashion (https://forums.alliedmods.net/showthread.php?t=28128)

Urahara 05-07-2006 20:38

Tutorial: Catching Weapons Fire in mod inspecific fashion
 
1 Attachment(s)
This tutorial brought to you by: Urahara
More tutorials, as well as additional assistance, can be found at:
http://urahara.amxmodx.org/forums/


This doesn't seem like such a hard thing to figure out; after all, mods do it all the time. However, it becomes rather tricky once you realize four things:

1. Mods don't all follow the same standards.
2. Mini-mods can fuck with buttons.
3. Melee and explosive devices don't use trace line
4. There are tons of trace lines sent out each second


However, by briefly looking in the HLSDK, we can see that these three Trace_*'s are used:

trace_line - guns
trace_hull - melee
trace_sphere - explosives


However, all three types of weapons use trace_line. So, we will start with trace_line.

Hooking trace_line with FM is a simple task; unfortunately, trace_line doesn't say what entity fired the trace_line, for speed.

To get a place to start, we'll consider this:

1. The starting point for firing a weapon is the player who fired.
2. The end point for firing a weapon is where it hits.


So, in theory, if we loop through the clients, comparing their origins and points of convergence for sight to the trace_line, we should come up with who fired!

Lets make some code!
Code:

public check_trace( Float:start[3], Float:end[3], monsters, skip_ent, TraceResult:ptr)
{
        new Players[32]
        new playerCount, i, player
        get_players(Players, playerCount, "a")

        new Float:origin[3];
        for (i=0; i<playerCount; i++)
        {
                player = Players[i];
                entity_get_vector(player,EV_VEC_origin,origin)

                if(is_my_traceline(start,origin) == 1) server_print("%i fired a shot!",player)
        }
               
}

As you can see, I edited out the end point origin, both for speed and for transparency.

Unfortunately, we hit a problem: The z origin is always different. Why? Because the gun is the one shooting, not the player. In order to keep with mod independence, we simply ignore the z origin. In addition, we need this:

Code:

#define XS_FLEQ_TOLERANCE 5.0
#define XS_FLEQ(%1,%2) (((%1) <= ((%2) + XS_FLEQ_TOLERANCE)) && ((%1) >= ((%2) - XS_FLEQ_TOLERANCE)))


public is_my_traceline(Float:one[3],Float:two[3])
{
        if( XS_FLEQ(one[0],two[0]) && XS_FLEQ(one[1],two[1]) /*&& (one[2] == two[2])*/ ) return 1;

        return 0;
}

Why is the tolerance so high? Lag and client prediction. The client could move a bit before we get his shot. In reality, no one can come close enough to a client under normal circumstances to interfer with this, so its fine.

As you might see, this is a little ineffecient. We could be losing a lot of speed, but at least it works, and always works. However, we can make it better.

The gun must not shoot the player aiming it. That would be bad; you'd kill yourself. :D So, lets assume that skip_ent will be the id of the shooter:

Code:

public check_trace( Float:start[3], Float:end[3], monsters, skip_ent, TraceResult:ptr)
{
        if(skip_ent > 0 && skip_ent <= get_maxplayers() ) server_print("%i fired a shot!",skip_ent)
}

Much more effecient, eh? Unfortunately, its also unreliable; some mods use trace_lines for other things, notably TS, which uses it for stunts. So, we can get false positives.

Since sending out a forward to other plugins is MUCH more expensive, speed wise, then doing a few math checks, we cna increase the speed of this function by adding back in some origin checking:

Code:

public check_trace( Float:start[3], Float:end[3], monsters, skip_ent, TraceResult:ptr)
{
        if(skip_ent > 0 && skip_ent <= get_maxplayers() )
        {
                new Float:origin[3]
                entity_get_vector(skip_ent,EV_VEC_origin,origin)

                if(is_my_traceline(start,origin) == 1) server_print("%i fired a shot!",skip_ent)
        }
}

In effect, we now have three versions of the same functions: One that has no false positives or negatives, but is computational expensive, one that has false positives, but is very cheap, and now one that is cheap and has no false positives or negatives.

Putting in the appropriate formatting, and add a few more bells and whistles, we have our plugin, which is uploaded below.

Feel free to use this as much as you like.

Xanimos 05-07-2006 21:01

Good tut Urahara! Signing up on your forums now!

Brad 05-07-2006 21:27

Ohayo! Nice Urahara. :up:

VEN 05-08-2006 05:27

Urahara:

Tutorials are good thing but in this case you obviously missed main point.
Traceline is a traceline and even such entity and origin checks will not tell us whether shot was fired or not.
Traceline is an "universal tool" which engine uses for doing many things and to filter out shot event you have to do more complicated work than that (at least with that method).

Also last player on the server (if it's connected) shouldn't be ignored in that code: skip_ent <= get_maxplayers()

Urahara 05-08-2006 08:16

Quote:

Originally Posted by VEN
Urahara:

Tutorials are good thing but in this case you obviously missed main point.
Traceline is a traceline and even such entity and origin checks will not tell us whether shot was fired or not.
Traceline is an "universal tool" which engine uses for doing many things and to filter out shot event you have to do more complicated work than that (at least with that method).

Also last player on the server (if it's connected) shouldn't be ignored in that code: skip_ent <= get_maxplayers()

Ohayo VEN-san! :D

Arigato for the last bit; i forgot about the final player, very very cruel of me poor last player :cry:

i dont mean to disagree, however, there is no other application of trace_line which starts at a players origin and ends at the players aiming points besides the firing of a weapon-type trace_line.

this method which i have created was tested to a significant degree and only occurs on firing of some sort of weapon; i do agree that simply checking the skip entity can render false positives, but by checking the origin, these are eliminated.

while trace_line is traceline, as you stated, and it is a universal engine function, there is no other use for it under this context besides firing a weapon. this can be proved through statistical analysis as well as by looking through the SDK, as well as testing on mods; it is not used in this manner for anything other than checking for the paths of bullets

thank you for your helpful reply though :D

VEN 05-08-2006 10:24

Quote:

there is no other application of trace_line which starts at a players origin and ends at the players aiming points besides the firing of a weapon-type trace_line
I can not agree with your point.
You probably overlooked that trace_line is used for many things, for example, when game mod trying to determine whether entity/point visible to a player/monster or not. I don't think you fully understand what is trace_line and how it works (at least i think so because of what you posted here).

Quote:

this method which i have created was tested to a significant degree and only occurs on firing of some sort of weapon
Well, you probably didn't tested that method with CS? And i've tested it and can tell you that your ShotsFired[skip_ent] will be equal to something like 999... after short time interval. The reason is because (at least in CS) such lines traces from player's origin (skipping it's entity) very often. And therefore you can't say "player fired a shot" just because of that trace.

Geesu 07-09-2006 23:10

Re: Tutorial: Catching Weapons Fire in mod inspecific fashion
 
Out of curiosity, I didn't see a hook for the melee or explosive attack "types"...

I didn't think FM_Traceline would hook these, how would you do this to catch knife + grenades?

VEN 07-11-2006 16:10

Re: Tutorial: Catching Weapons Fire in mod inspecific fashion
 
Quote:

I didn't see a hook for the melee or explosive attack "types"...
He tried to use that method to detect an aimbot (which is ture only for handguns/shotguns/(sub-)machine guns/rifles).

Geesu 07-11-2006 16:19

Re: Tutorial: Catching Weapons Fire in mod inspecific fashion
 
Quote:

Originally Posted by VEN
He tried to use that method to detect an aimbot (which is ture only for handguns/shotguns/(sub-)machine guns/rifles).

I'm confused, what are you talking about?

I wanted to try to catch knife/grenade ?

VEN 07-11-2006 16:39

Re: Tutorial: Catching Weapons Fire in mod inspecific fashion
 
The thread's name is "Tutorial: Catching Weapons Fire in mod inspecific fashion".
Author have created this tutorial while working on aimbot detection.
An aimbot is usually used with handguns/shotguns/(sub-)machine guns/rifles.
When he wrote "fire" i think it's obviously that he mean only the weapons listed above and not knife/grenade.

EDIT: while he mentioned explosives/melee it doesnt seems like he tried to detect explosives/melee attacks.


All times are GMT -4. The time now is 10:59.

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