AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Code Snippets/Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=83)
-   -   Automatic func_tanks in Counter Strike (https://forums.alliedmods.net/showthread.php?t=126074)

joaquimandrade 05-05-2010 07:26

Automatic func_tanks in Counter Strike
 
1 Attachment(s)
Hello. I was searching for random functions to test with orpheu and got curious about func_tanks. They have auto aiming and shooting functionality but it doesn't work out of the box in CS so I tried to unlock it. The process is easy: we just have to make them think, have basic flags, and override its search for players because it's code inherited from halflife searches for players in PVS but it seems that they don't have one in CS :P.

The code:

Code:

public plugin_precache()
{
    RegisterHam(Ham_Spawn,"func_tank","spawnTank",1)   
    OrpheuRegisterHook(OrpheuGetEngineFunction("pfnFindClientInPVS","FindClientInPVS"),"OnFindClientInPVS")
}

public spawnTank(id)
{
    set_pev(id,pev_spawnflags, SF_TANK_ACTIVE | SF_TANK_PLAYER | SF_TANK_HUMANS | SF_TANK_CANCONTROL | SF_TANK_SOUNDON)
    dllfunc(DLLFunc_Think,id)
}

public OrpheuHookReturn:OnFindClientInPVS(id)
{
    OrpheuSetReturn(find_ent_by_class(0,"player"))
    return OrpheuSupercede
}

Arkshine told me that the only flag really needed is SF_TANK_ACTIVE and you can see more about them in hlsdk.

If you want to use this code in a zombie server or something like that just change the function OnFindClientInPVS and use on it an algorithm of yours to find a player to shoot at (like the closer zombie or whatever).

Final notes:
It almost could be made without orpheu because fakemeta also provides hooking for FindClientInPVS but I tested it and it didn't get called.

Offsets for CFuncTank - http://wiki.amxmodx.org/CFuncTank_%28CS%29

FindClientInPVS can be also called in more situations for other entities (though is unusual) so you might want to add it's hook an extra check to see if it is a func_tank using it.

Thanks to Capostrike for testing with me :D

Example map: http://www.fpsbanana.com/maps/1080

capostrike93 05-05-2010 07:48

Re: Automatic func_tanks in Counter Strike
 
Demonstration video: ...

http://www.xfire.com/video/29f364/

please see 2:25 minutes

here useful example:

PHP Code:

#include <amxmodx>
#include <orpheu>
#include <orpheu_stocks>
#include <fakemeta>
#include <hamsandwich>
#include <xs>

#define KILL_ONLYT // Kill only Terrorist Team...
// #define KILL_ONLYCT // Kill only Counter-Terrorist Team...
// #define ZOMBIEPLAGUE // For zombie plague mod...

#if defined ZOMBIEPLAGUE
#include <zombieplague>
#elseif defined KILL_ONLYT || defined KILL_ONLYCT
#include <cstrike>
#endif

public plugin_precache()
{
    
register_plugin("Example Advanced Spawn Tank","1.0","capostrike93/joaquim")
    
RegisterHam(Ham_Spawn,"func_tank","spawnTank",1)    
    
OrpheuRegisterHook(OrpheuGetEngineFunction("pfnFindClientInPVS","FindClientInPVS"),"OnFindClientInPVS")
}

public 
spawnTank(id)
{
    
set_pev(id,pev_spawnflagsSF_TANK_ACTIVE SF_TANK_PLAYER SF_TANK_HUMANS SF_TANK_CANCONTROL SF_TANK_SOUNDON)
    
dllfunc(DLLFunc_Think,id)
    
set_pdata_float(id,41,360.0,4)
}

public 
OrpheuHookReturn:OnFindClientInPVS(id)
{
    
OrpheuSetReturn(findCloserPlayer(id))
    return 
OrpheuSupercede
}

findCloserPlayer(id)
{
    new 
Float:originFTank[3]
    
pev(id,pev_origin,originFTank)
    
    static
    
Float:originFPlayer[3],
    
Float:Distance,
    
Float:CloserDistance;

    
// Reset Distance
    
CloserDistance 999999.0;
    
    new 
CloserPlayer
    
    
for(new i;i<33;i++)
    {
        if(!
is_user_alive(i)) continue
        
#if defined ZP
        
if(!zp_get_user_zombie(i)) continue
        
#endif
        #if defined KILL_ONLYT
        
if(cs_get_user_team(i) != CS_TEAM_T) continue
        
#endif
        #if defined KILL_ONLYCT
        
if(cs_get_user_team(i) != CS_TEAM_CT) continue
        
#endif
        
        
pev(i,pev_origin,originFPlayer)
        
        
Distance get_distance_f(originFTank,originFPlayer)
        if(
CloserDistance Distance)
        {
            
CloserPlayer i;
            
CloserDistance Distance;
        }
    }
    
    return 
CloserPlayer;


set_pdata_float(id,41,360.0,4) // For full rotation (360º)

fezh 05-05-2010 13:01

Re: Automatic func_tanks in Counter Strike
 
Good stuff, gonna test it.

capostrike93 05-05-2010 19:36

Re: Automatic func_tanks in Counter Strike
 
set_pdata_float(id,41,360.0,4) // For full rotation (360º)

AntiBots 05-05-2010 20:44

Re: Automatic func_tanks in Counter Strike
 
Caostrike, you example they will only shoot people with the last index in the Radio.

You understand me?

joropito 05-05-2010 21:41

Re: Automatic func_tanks in Counter Strike
 
It works using fakemeNta too

(I'm using random 1-32 because I'm too lazy to make it better :P)

PHP Code:

#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>

public plugin_init()
{
        
register_forward(FM_FindClientInPVS"findclientinpvs")
}

public 
plugin_precache()
{
        
RegisterHam(Ham_Spawn,"func_tank","spawnTank",1)
}

public 
spawnTank(id)
{
        
set_pev(id,pev_spawnflagsSF_TANK_ACTIVE SF_TANK_PLAYER SF_TANK_HUMANS SF_TANK_CANCONTROL SF_TANK_SOUNDON)
        
dllfunc(DLLFunc_Think,id)
}

public 
findclientinpvs(id)
{
        static class[
32]
        if(
pev_valid(id))
        {
                
pev(idpev_classname, class, charsmax(class))
                if(
equal(class, "func_tank"))
                {
                        
forward_return(FMV_CELLrandom_num(132))
                        return 
FMRES_SUPERCEDE
                
}
        }
        return 
FMRES_IGNORED



joaquimandrade 05-05-2010 21:47

Re: Automatic func_tanks in Counter Strike
 
But have you tested? When I tested, FM_FindClientInPVS didn't get called.

joropito 05-05-2010 21:48

Re: Automatic func_tanks in Counter Strike
 
Yes, I have tested.

Maybe you miss using forward_return or you use findentityinpvs instead of clientinpvs, I don't know but it's working.

joaquimandrade 05-05-2010 21:51

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by joropito (Post 1172098)
Yes, I have tested.

Maybe you miss using forward_return or you use findentityinpvs instead of clientinpvs, I don't know but it's working.

I remember testing the right forward but anyway, if it works, it works.

joropito 05-05-2010 21:52

Re: Automatic func_tanks in Counter Strike
 
Here's the key name/values used for func_tank
(cs_rats2_final example values)

Code:

model *174
origin -35 576 -198
rotatesound ambience/turretrot1.wav
rendermode 0
renderfx 0
spriteflash sprites/muzzleflash2.spr
bullet 3
maxRange 0
minRange 0
firespread 1
persistence 1
bullet_damage 15
firerate 15
spritescale 1
barrelz 7
barrely 0
barrel 66
pitchtolerance 5
pitchrange 75
pitchrate 500
yawtolerance 15
yawrange 55
yawrate 500
target boom
rendercolor 0 0 0
renderamt 0
targetname gunny
spawnflags 32


capostrike93 05-05-2010 23:17

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by AntiBots (Post 1172031)
Caostrike, you example they will only shoot people with the last index in the Radio.

You understand me?

no, my example does that attack the player closest to the tank ..
by default only attack to team terrorist

#define KILL_ONLYT

capostrike93 05-05-2010 23:20

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by joropito (Post 1172091)
It works using fakemeNta too

(I'm using random 1-32 because I'm too lazy to make it better :P)

PHP Code:

#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>

public plugin_init()
{
        
register_forward(FM_FindClientInPVS"findclientinpvs")
}

public 
plugin_precache()
{
        
RegisterHam(Ham_Spawn,"func_tank","spawnTank",1)
}

public 
spawnTank(id)
{
        
set_pev(id,pev_spawnflagsSF_TANK_ACTIVE SF_TANK_PLAYER SF_TANK_HUMANS SF_TANK_CANCONTROL SF_TANK_SOUNDON)
        
dllfunc(DLLFunc_Think,id)
}

public 
findclientinpvs(id)
{
        static class[
32]
        if(
pev_valid(id))
        {
                
pev(idpev_classname, class, charsmax(class))
                if(
equal(class, "func_tank"))
                {
                        
forward_return(FMV_CELLrandom_num(132))
                        return 
FMRES_SUPERCEDE
                
}
        }
        return 
FMRES_IGNORED



well, but it is clear that has to verify the integrity of random_num

I mean a. player is alive? check team? other?

and I almost forgot..

add
set_pdata_float(id,41,360.0,4) // For full rotation (360º)

:P

joropito 05-06-2010 08:33

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by capostrike93 (Post 1172139)
well, but it is clear that has to verify the integrity of random_num

I mean a. player is alive? check team? other?

It was just a test the fakemeta alternative. It's just an example.

Quote:

Originally Posted by capostrike93 (Post 1172139)
set_pdata_float(id,41,360.0,4) // For full rotation (360º)

Only if I need :P

Btw, I think it's possible to set full rotation using key "yawrange".

Arkshine 05-06-2010 08:50

Re: Automatic func_tanks in Counter Strike
 
If you want to use the keyvalue, I guess you need to hook the spawn as pre.

Like Quim said, you can get a list of offsets there http://wiki.amxmodx.org/CFuncTank_(CS) ; and you can see the name is enough explicit to understand the keyvalue name related :

Code:

void CFuncTank :: KeyValue( KeyValueData *pkvd )
{
        if (FStrEq(pkvd->szKeyName, "yawrate"))
        {
                m_yawRate = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "yawrange"))
        {
                m_yawRange = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "yawtolerance"))
        {
                m_yawTolerance = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "pitchrange"))
        {
                m_pitchRange = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "pitchrate"))
        {
                m_pitchRate = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "pitchtolerance"))
        {
                m_pitchTolerance = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "firerate"))
        {
                m_fireRate = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "barrel"))
        {
                m_barrelPos.x = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "barrely"))
        {
                m_barrelPos.y = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "barrelz"))
        {
                m_barrelPos.z = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "spritescale"))
        {
                m_spriteScale = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "spritesmoke"))
        {
                m_iszSpriteSmoke = ALLOC_STRING(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "spriteflash"))
        {
                m_iszSpriteFlash = ALLOC_STRING(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "rotatesound"))
        {
                pev->noise = ALLOC_STRING(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "persistence"))
        {
                m_persist = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "bullet"))
        {
                m_bulletType = (TANKBULLET)atoi(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if ( FStrEq(pkvd->szKeyName, "bullet_damage" ))
        {
                m_iBulletDamage = atoi(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "firespread"))
        {
                m_spread = atoi(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "minRange"))
        {
                m_minRange = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "maxRange"))
        {
                m_maxRange = atof(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else if (FStrEq(pkvd->szKeyName, "master"))
        {
                m_iszMaster = ALLOC_STRING(pkvd->szValue);
                pkvd->fHandled = TRUE;
        }
        else
                CBaseEntity::KeyValue( pkvd );
}

But I guess it would be more appropriate to work with keyvalue when you can.

Seta00 05-06-2010 11:16

Re: Automatic func_tanks in Counter Strike
 
This is awesome, good work. It's amazing how the CS modding capabilities are still growing after all these years.

capostrike93 05-06-2010 23:43

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by joropito (Post 1172462)
It was just a test the fakemeta alternative. It's just an example.



Only if I need :P

Btw, I think it's possible to set full rotation using key "yawrange".

ammm xD??

...

m_yawRange is num 41
set_pdata_float(id,41,360.0,4)

:wink:

http://wiki.amxmodx.org/CFuncTank_%28CS%29

Arkshine 05-07-2010 06:08

Re: Automatic func_tanks in Counter Strike
 
It's more safe to deal with keyvalues than offset since this one can change on update. So if you can, use keyvalues.

Also, if I'm right ( but I've seen some tutorials saying the same thing ), to have a full rotation you should write 180, 180 left + 180 right = 360. Like the Joropito's example : "yawrange 55" ; meaning the range is : 55 + 55 = 110.

joropito 05-07-2010 08:54

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by Arkshine (Post 1172489)
If you want to use the keyvalue, I guess you need to hook the spawn as pre

Why must be done at precache (in func_tank case)?

This should work (not tested).

PHP Code:

set_kvd(0KV_ClassName"func_tank")
set_kvd(0KV_KeyName"yawrange")
set_kvd(0KV_Value180)
set_kvd(0KV_fHandled0)
dllfunc(DLLFunc_KeyValueent0

In hlsdk I can see that at CFuncTank::KeyValue() every offset is updated with the new values.

Arkshine 05-07-2010 09:53

Re: Automatic func_tanks in Counter Strike
 
I have read somewhere after using DispatchKeyValue you must use DispatchSpawn but looking the HLSDK I don't find any reference to that, so I guess it should work right away. I'm going to try to see.

joropito 05-07-2010 10:29

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by Arkshine (Post 1173341)
I have read somewhere after using DispatchKeyValue you must use DispatchSpawn but looking the HLSDK I don't find any reference to that, so I guess it should work right away. I'm going to try to see.

Yeah, maybe that dispatch it's for some entities but for func_tank it seems to be quite different unless CFuncTank::KeyValue isn't related to DLLFunc_KeyValue.

Arkshine 05-07-2010 14:53

Re: Automatic func_tanks in Counter Strike
 
You're right, I've tested with this following plugin, type "tank" to spawn an entity in front of you, by default the yaw range is 110°, and if you type "range" it will update the range to 360° and it's well updated right away without needed to spawn again.

PHP Code:


    
#include <amxmodx>
    #include <fakemeta>
    #include <hamsandwich>
    #include <engine>
    #include <xs>
    
    
const MAX_CLIENTS  32;
    const 
MAX_ENTITIES = ( 900 + ( MAX_CLIENTS 15 ) ) / 32;

    new 
isTankMAX_ENTITIES ];

    
#define SetIsTank(%1)     ( isTank[ %1 >> 5 ] |=  ( 1 << ( %1 & 31 ) ) )
    #define ClearIsTank(%1)   ( isTank[ %1 >> 5 ] &= ~( 1 << ( %1 & 31 ) ) )
    #define IsTank(%1)        ( isTank[ %1 >> 5 ] &   ( 1 << ( %1 & 31 ) ) )

    
public plugin_precache()
    {
        
register_forwardFM_Spawn"Entities_Spawn" );
        
        
precache_model"models/turret.mdl" );
        
precache_model"sprites/muzzleflash2.spr" );
        
precache_sound"ambience/turretrot1.wav" );
    }

    public 
Entities_Spawn ( const entity )
    {
        new 
classname32 ];
        
peventitypev_classnameclassnamecharsmaxclassname ) );

        if ( 
pev_validentity ) )
        {
            
equalclassname"func_tank" ) ? SetIsTankentity ) : ClearIsTankentity );
        }
    }

    public 
plugin_init()
    {
        
register_plugin"""""" );
        
        
register_forwardFM_FindClientInPVS"FindClientInPVS" );
        
        
register_clcmd"tank" "ClientCommand_CreateTank" );
        
register_clcmd"range""ClientCommand_ChangeRange" );
    }

    public 
ClientCommand_CreateTank ( const client )
    {
        new 
Float:origin]
        
GetAimOriginDistanceclientorigin200.0 );
    
        new 
tank create_entity"func_tank" );
        
        
engfuncEngFunc_SetModeltank"models/v_m4a1.mdl" );
        
engfuncEngFunc_SetOrigintankorigin );

        
DispatchKeyValuetank"rotatesound"  "ambience/turretrot1.wav"  );
        
DispatchKeyValuetank"spriteflash"  "sprites/muzzleflash2.spr" );
        
DispatchKeyValuetank"spritescale"  "1" );
        
DispatchKeyValuetank"bullet"       "1" );
        
DispatchKeyValuetank"firespread"   "1" );
        
DispatchKeyValuetank"persistence"  "1" );
        
DispatchKeyValuetank"bullet_damage""1" );
        
DispatchKeyValuetank"firerate"     "15"  );
        
DispatchKeyValuetank"yawrate"      "500" );
        
DispatchKeyValuetank"yawrange"     "55"  );
        
DispatchKeyValuetank"yawtolerance" "5"   );
        
DispatchKeyValuetank"pitchrate"    "500" );
        
DispatchKeyValuetank"pitchrange"   "55"  );
        
DispatchKeyValuetank"pitchtolerance""5"  );
        
DispatchKeyValuetank"barrelz"      "4"   );
        
DispatchKeyValuetank"barrely"      "0"   );
        
DispatchKeyValuetank"barrel"       "30"  );
        
        
set_pevtankpev_spawnflagsSF_TANK_ACTIVE );
        
DispatchSpawntank );
    }
    
    public 
ClientCommand_ChangeRange ( const client )
    {
        new 
tank FM_NULLENT;
        
        while ( ( 
tank find_ent_by_classtank"func_tank" ) ) )
        {
            
DispatchKeyValuetank"yawrange""180" );
        }
        
        return 
PLUGIN_HANDLED;
    }   

    public 
FindClientInPVS ( const entity )
    {
        if ( 
IsTankentity ) )
        {
            
forward_returnFMV_CELLfind_ent_by_class0"player" ) );
            return 
FMRES_SUPERCEDE;
        }
        
        return 
FMRES_IGNORED;
    }
    
    
GetAimOriginDistanceindexFloat:origin], Float:distance 
    {
        new 
Float:start];
        new 
Float:view_ofs];
        
        
pevindexpev_originstart );
        
pevindexpev_view_ofsview_ofs );
        
        
xs_vec_addstartview_ofsstart );

        new 
Float:dest];
        
pevindexpev_v_angledest );
        
        
engfuncEngFunc_MakeVectorsdest );
        
global_getglb_v_forwarddest );
        
        
xs_vec_mul_scalardestdistancedest );
        
xs_vec_addstartdestdest );

        
engfuncEngFunc_TraceLinestartdestIGNORE_MONSTERSindex);
        
get_tr20TR_vecEndPosorigin );
    } 


EXteRmiNaToR 05-08-2010 06:04

Re: Automatic func_tanks in Counter Strike
 
Nice plugin Arkshine!:)
Is it possible to make it be "unfriendly" to specific players?

Arkshine 05-08-2010 06:13

Re: Automatic func_tanks in Counter Strike
 
This plugin was just a test, it should not be used like that, but for what you ask, you have to do like in #2, looping through all players and adding your filters instead of using directly find_ent_by_class().

EXteRmiNaToR 05-08-2010 06:21

Re: Automatic func_tanks in Counter Strike
 
Okay,will do that.Thanks for your answer!

hjkwe654 06-20-2010 01:57

Re: Automatic func_tanks in Counter Strike
 
Quote:

Originally Posted by joaquimandrade (Post 1171235)
Hello. I was searching for random functions to test with orpheu and got curious about func_tanks. They have auto aiming and shooting functionality but it doesn't work out of the box in CS so I tried to unlock it. The process is easy: we just have to make them think, have basic flags, and override its search for players because it's code inherited from halflife searches for players in PVS but it seems that they don't have one in CS :P.

The code:

......

It only target 1 player.
when the player dead, tank still target that player

Arkshine 06-20-2010 06:09

Re: Automatic func_tanks in Counter Strike
 
See the second post. You have to filter. It was just an example.


All times are GMT -4. The time now is 13:55.

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