Raised This Month: $32 Target: $400
 8% 

Blocking weapon fire, including client-side sounds/animations


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
KCE
Senior Member
Join Date: Jan 2005
Location: Los Angeles, CA
Old 07-12-2006 , 05:30   Blocking weapon fire, including client-side sounds/animations
Reply With Quote #1

Blocking weapon fire, including client-side sounds/animations

So you want to block weapon fire, including client-side sounds/animations?...you've come to the right thread

This tutorial is meant for intermediate - advanced users

Introduction
  • I've been using this method in my metamod MLMod plugin for NS, for a while now, which is similar to the metamod Spawn Chat protection plugin by Jussi Kivilinna. I have not tested this is any other mod except NS, but it should work the same...
  • With the addition of UpdateClientData forward in the latest Amx Mod X, it is now possible to block weapon fire through fakemeta, including client-side sounds/animations.
  • There are two methods to blocking weapon fire:
    1. Make the engine think the player has no weapon - for blocking weapon fire whenever you want to
    2. Set the time until next attack (used in the Spawn Chat protection plugin) - for blocking weapon fire for a specific amount of time
  • Info on the UpdateClientData function...
    • It appears to be called every frame and also before PreThink.
    • Setting player properties like EV_ or pev_ do not work (I've tested with removing buttons from EV_INT_buttons and does not block it).
    • It cannot block reload animations. Doing either of the methods above during a reload will not block the animation. However, weapon reload can be blocked (the anim and actual reload) by removing the buttons.
  • Also, you MUST STILL remove the IN_ATTACK button mask to keep the weapon from using ammo and doing damage, etc. Like I said, you cannot do this in UpdateClientData, so it must be done in PreThink or CmdStart like before. However, I'm not sure if CmdStart is called every frame? I recommend PreThink because it is called specifically before Think and PostThink and every frame.

Now for the good part...

Registering forwards and hooks
  1. Import the additional includes that you will need.
    Code:
    #include <fakemeta> #include <engine>
  2. In plugin_init(), register FM_PlayerPreThink or use the default engine client_preThink. If registering through fakemeta, it does not matter if it is post or not. The engine forward is not post meaning it is called before the original is called.
    Code:
    public client_PreThink(id) { }
    or
    Code:
    register_forward(FM_PlayerPreThink, "PlayerPreThink")
  3. And also in plugin_init(), register FM_UpdateClientData. It is important that it is hooked AFTER the original is called so your modifications are not changed. This is indicated by passing 1 as the third argument telling Amx Mod X that you want your function to get called after the original has been called.
    Code:
    register_forward(FM_UpdateClientData, "UpdateClientData_Post", 1)
  4. In client_preThink, if you're using the default engine forward, if using fakemeta method then whatever it is you named it. In my example it was named PlayerPreThink
    Code:
    //engine method public client_PreThink( id ) {     //Do whatever checks you need to do and whatnot...         if( !is_user_alive(id) )         return PLUGIN_CONTINUE;         //Remove the attack button from their button mask         entity_set_int( id, EV_INT_button, entity_get_int(id,EV_INT_button) & ~IN_ATTACK );     return PLUGIN_CONTINUE; }
    or
    Code:
    //fakemeta method public PlayerPreThink( id ) {     //Do whatever checks you need to do and whatnot...         if( !is_user_alive(id) )         return FMRES_IGNORED;         //Remove the attack button from their button mask         set_pev( id, pev_button, pev(id,pev_button) & ~IN_ATTACK );     return FMRES_HANDLED; }
  5. In UpdateClientData_Post, there are 3 arguments sent:
    1. 1st argument is id (int) - player ID
    2. 2nd argument is sendweapons (int) - indication if client-side weapons are being used (cl_lw); not really important, can be ignored
    3. 3rd argument is cd_handle (clientdata type) - contains all the player info to be modified, which is accessed through get_cd, and set_cd
    Code:
    public UpdateClientData_Post( id, sendweapons, cd_handle ) { }

Method 1 - Make the engine think the player has no weapon:
  • We do this by modifying CD_ID, which is the weapon id, and setting it to 0 thus making the engine think the player has no weapon and so no animation/sound can be played.
    Code:
    //Remember the 3 arguments sent: //id - player id //sendweapons - indication if client-side weapons are being used (cl_lw) //cd_handle - client data which is accessed through get_cd, and set_cd public UpdateClientData_Post( id, sendweapons, cd_handle ) {     //No sense in doing this for dead people?     //Add your additional checks and whatnot...     if ( !is_user_alive(id) )         return FMRES_IGNORED;     //We want to use the cd_handle passed to us     //unless you want this for all the players     //in which you would specify 0 instead         set_cd(cd_handle, CD_ID, 0);                //And finally return...         return FMRES_HANDLED; }

Method 2 - Modify the time until the next attack:
  • We do this by modifying CD_flNextAttack, which is the specific time when the player can attack again. This cannot only be used to block attacks but to also modify ROF! (which I'll discuss elsewhere).
  • Actually CD_flNextAttack has a value greater than zero ONLY when a player is reloading which is why it acts the way it does. So basically setting this value makes the engine think the player is in reload, however the reload animations are not played. Another way this could be used is possibly to make the player fire before the reload is done?
    Code:
    //Again the 3 arguments sent: //id - player id //sendweapons - indication if client-side weapons are being used (cl_lw) //cd_handle - client data which is accessed through get_cd, and set_cd public UpdateClientData_Post( id, sendweapons, cd_handle ) {     //No sense in doing this for dead people?     //Add your additional checks and whatnot...     if ( !is_user_alive(id) )         return FMRES_IGNORED;     //We want to use the cd_handle passed to us     //unless you want this for all the players     //in which you would specify 0 instead         //We get the current half-life time and set the next attack to a fraction of a sec later...     //This must be modified every time or else it won't block the attack     set_cd(cd_handle, CD_flNextAttack, halflife_time() + 0.001 );               //And finally return...         return FMRES_HANDLED; }
  • A snippet from the Spawn Chat protection plugin and how it uses this function. My comments start with four slashes ////.
    Code:
    void CPlayer::UpdateClientData_Post(int sendweapons, struct clientdata_s *cd)
    {
    	//Fix clientside weapon animations
    	if(sendweapons && m_ProtectionActive)
    	{
    		////The first part of the if statement let's the player attack the next frame
    		////The second part of the if statement blocks the player's attack until a certain time
    	
    		////If attack time is before the current time (meanning player can fire) then 
    		if (cd->m_flNextAttack < gpGlobals->time)			
    			
    			////m_StartOfProtection is the time when the blocking of the player's attack started
    			////scp_off_delay.get() is how long to keep blocking the time
    			////m_StartOfProtection + scp_off_delay.get() is the time when the player can attack again
    			////(m_StartOfProtection + scp_off_delay.get()) - (gpGlobals->time + 0.001f)
    			////Think of it as:
    			////<time when the player can attack again> - <time now, basically> = now or next frame player can attack
    			////Pretty much, the player can attack the moment they want to and it won't be blocked
    			////The 0.001 is so player can fire a fraction of a second earlier to fix some weapon glitches or because it is checked by > instead of equal
    			cd->m_flNextAttack = (m_StartOfProtection + scp_off_delay.get()) - (gpGlobals->time + 0.001f);
    		
    		////else if attack time is after the current time (meanning player can't fire) then 
    		else
    		
    			////Similar to above except in calculations...
    			////m_StartOfProtection is the time when the blocking of the player's attack started
    			////scp_off_delay.get() is how long to keep blocking the time
    			////m_StartOfProtection + scp_off_delay.get() is the time when the player can attack again
    			////(m_StartOfProtection + scp_off_delay.get()) - 0.001f
    			////Think of it as:
    			////<time when the player can attack again> - <fraction of a second> = specific time when player can attack
    			////The 0.001 is so player can fire a fraction of a second earlier to fix some weapon glitches or because it is checked by > instead of equal
    			cd->m_flNextAttack = (m_StartOfProtection + scp_off_delay.get()) - 0.001f;
    		
    		SetMetaResult(MRES_HANDLED);
    		return;
    	}
    	
    	SetMetaResult(MRES_IGNORED);
    	return;
    }

Custom Weapon ROF (Rate-of-fire)
  • I did this part on-the-fly...anyways there are, of course, many ways to do this. This is just one way; there may be others methods that could be better suited for your situation; just take a look at the above snippet from the Spawn Chat protection plugin.
  • Also the subtraction of the 0.001 is not neccessary but feel free to do it if needed. I believe it is done because it is checked with greater than (>) so the delay is slightly longer but only by a very miniscule amount.
  • Create some variables to store some info:
    Code:
    new g_NextAttack[33];   //stores players' next attack times new g_BlockAnim[33];    //stores players' variable for whether to block animation in UpdateClientData_Post new CVAR_rof;         //"pointer" to CVAR containing the rof; could also be define
  • Using Method #1:
    • In UpdateClientData_Post is where we initially decide whether the attack needs to be blocked
      Code:
      //Remember the 3 arguments sent: //id - player id //sendweapons - indication if client-side weapons are being used (cl_lw) //cd_handle - client data which is accessed through get_cd, and set_cd public UpdateClientData_Post( id, sendweapons, cd_handle ) {     //Do whatever checks you need to do and whatnot...     //Make sure player is holding the weapon you want to block     //Make sure player is alive     //etc.         //First check the ROF         //Store the variables         new Float:global_Time;     global_get(glb_time, global_Time);     new Float:ROF = get_pcvar_float(CVAR_rof);         //If current time hasn't yet reached the next allowed attack time, keep blocking the attack     //else let it go and reset the g_BlockAnim variable         if( global_Time < g_NextAttack[id] )     {         //Keep blocking attack         //Now you could just block if the player is pressing the button but just to be safe block it regardless                 //Set player variable to block in PlayerPreThink also                 g_BlockAnim[id] = 1;                 //We want to use the cd_handle passed to us         //unless you want this for all the players         //in which you would specify 0 instead                    set_cd(cd_handle, CD_ID, 0);            }     else     {         //Allow attack                 //Reset player variable to block in PlayerPreThink                 g_BlockAnim[id] = 0;                 //Set next attack time at which player is allowed to attack                 g_NextAttack[id] = global_Time + ROF;           }         return FMRES_HANDLED; }
  • Using Method #2:
    • In UpdateClientData_Post is where we initially decide whether the attack needs to be blocked
      Code:
      //Remember the 3 arguments sent: //id - player id //sendweapons - indication if client-side weapons are being used (cl_lw) //cd_handle - client data which is accessed through get_cd, and set_cd public UpdateClientData_Post( id, sendweapons, cd_handle ) {     //Do whatever checks you need to do and whatnot...     //Make sure player is holding the weapon you want to block     //Make sure player is alive     //etc.         //First check the ROF         //Store the variables         new Float:global_Time;     global_get(glb_time, global_Time);     new Float:ROF = get_pcvar_float(CVAR_rof);         //If current time hasn't yet reached the next allowed attack time, keep blocking the attack     //else let it go and reset the g_BlockAnim variable         if( global_Time < g_NextAttack[id] )     {         //Keep blocking attack         //Now you could just block if the player is pressing the button but just to be safe block it regardless                 //Set player variable to block in PlayerPreThink also                 g_BlockAnim[id] = 1;         //We want to use the cd_handle passed to us         //unless you want this for all the players         //in which you would specify 0 instead                    //If current time is equal or greater than (>=) g_NextAttack, the attack will be blocked         //else it will not                 set_cd(cd_handle, CD_flNextAttack, g_NextAttack[id]);     }     else     {         //Allow attack                 //Reset player variable to block in PlayerPreThink                 g_BlockAnim[id] = 0;                 //Set next attack time at which player is allowed to attack                 g_NextAttack[id] = global_Time + ROF;           }     return FMRES_HANDLED; }
  • In PlayerPreThink we check the g_BlockAnim variable
    Code:
    //fakemeta method public PlayerPreThink( id ) {     //Do whatever checks you need to do and whatnot...     //Make sure player is holding the weapon you want to block     //Make sure player is alive     //etc.         if( g_BlockAnim[id] )     {         //Remove the attack button from their button mask                 set_pev( id, pev_button, pev(id,pev_button) & ~IN_ATTACK );                 //Reset the variable         //It will be set again in UpdateClientData_Post before it comes here so it is set every frame                 g_BlockAnim[id] = 0;     }     // else allow attack         return FMRES_HANDLED; }

Quick Reference:
  • From fakemeta_const.inc & fakemeta.inc:
  • ClientData enum
    Code:
    enum ClientData
    {
    	CD_Origin,			// float array[3]
    	CD_Velocity,		// float array[3]
    	CD_ViewModel,		// int
    	CD_PunchAngle,		// float array[3]
    	CD_Flags,			// int
    	CD_WaterLevel,		// int
    	CD_WaterType,		// int
    	CD_ViewOfs,			// float array[3]
    	CD_Health,			// float
    	CD_bInDuck,			// int
    	CD_Weapons,			// int
    	CD_flTimeStepSound,	// int
    	CD_flDuckTime,		// int
    	CD_flSwimTime,		// int
    	CD_WaterJumpTime,	// int
    	CD_MaxSpeed,		// float
    	CD_FOV,				// float
    	CD_WeaponAnim,		// int
    	CD_ID,				// int
    	CD_AmmoShells,		// int
    	CD_AmmoNails,		// int
    	CD_AmmoCells,		// int
    	CD_AmmoRockets,		// int
    	CD_flNextAttack,	// float
    	CD_tfState,			// int
    	CD_PushMsec,		// int
    	CD_DeadFlag,		// int
    	CD_PhysInfo,		// string[256]
    	CD_iUser1,			// int
    	CD_iUser2,			// int
    	CD_iUser3,			// int
    	CD_iUser4,			// int
    	CD_fUser1,			// float
    	CD_fUser2,			// float
    	CD_fUser3,			// float
    	CD_fUser4,			// float
    	CD_vUser1,			// float array[3]
    	CD_vUser2,			// float array[3]
    	CD_vUser3,			// float array[3]
    	CD_vUser4			// float array[3]
    };
  • ClientData functions
    Code:
    // These functions are used with the clientdata data structure (FM_UpdateClientData)
    // Get: 0 extra params - Return integer; 1 extra param - by ref float or vector; 2 extra params - string and length
    // Set: Use anything
    // Use 0 for cd_handle to specify the global clientdata handle
    native get_cd(cd_handle, ClientData:member, {Float,_}:...);
    native set_cd(cd_handle, ClientData:member, {Float,_}:...);
  • Forward Function Constants
    Code:
    enum {
    	FM_PrecacheModel = 1,		// done
    	FM_PrecacheSound,		// done
    	FM_SetModel,			// done
    	FM_ModelIndex,			// done
    	FM_ModelFrames,			// done
    	FM_SetSize,			// done
    	FM_ChangeLevel,			// done
    	FM_VecToYaw,			// done
    	FM_VecToAngles,			// done
    	FM_MoveToOrigin,		// done
    	FM_ChangeYaw,			// done
    	FM_ChangePitch,			// done
    	FM_FindEntityByString,		// done
    	FM_GetEntityIllum,		// done
    	FM_FindEntityInSphere,		// done
    	FM_FindClientInPVS,		// done
    	FM_EntitiesInPVS,		// done
    	FM_MakeVectors,			// done
    	FM_AngleVectors,		// done
    	FM_CreateEntity,		// done
    	FM_RemoveEntity,		// done
    	FM_CreateNamedEntity,		// done
    	FM_MakeStatic,			// done
    	FM_EntIsOnFloor,		// done
    	FM_DropToFloor,			// done
    	FM_WalkMove,			// int  )		(edict_t *ent, float yaw, float dist, int iMode); -- does't work as of 0.20 RC2
    	FM_SetOrigin,			// done
    	FM_EmitSound,			// done
    	FM_EmitAmbientSound,		// done
    	FM_TraceLine,			// void )		(const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr); -- does't work as of 0.20 RC2
    	FM_TraceToss,			// void )		(edict_t* pent, edict_t* pentToIgnore, TraceResult *ptr); -- does't work as of 0.20 RC2
    	FM_TraceMonsterHull,		// int  )		(edict_t *pEdict, const float *v1, const float *v2, int fNoMonsters, edict_t *pentToSkip, TraceResult *ptr); -- does't work as of 0.20 RC2
    	FM_TraceHull,			// void )		(const float *v1, const float *v2, int fNoMonsters, int hullNumber, edict_t *pentToSkip, TraceResult *ptr);  -- does't work as of 0.20 RC2
    	FM_TraceModel,			// void )		(const float *v1, const float *v2, int hullNumber, edict_t *pent, TraceResult *ptr);  -- does't work as of 0.20 RC2
    	FM_TraceTexture,		// const char *)	(edict_t *pTextureEntity, const float *v1, const float *v2 ); -- does't work as of 0.20 RC2
    	FM_TraceSphere,			// void )		(const float *v1, const float *v2, int fNoMonsters, float radius, edict_t *pentToSkip, TraceResult *ptr);  -- does't work as of 0.20 RC2
    	FM_GetAimVector,		// done
    	FM_ParticleEffect,		// done
    	FM_LightStyle,			// done
    	FM_DecalIndex,			// done
    	FM_PointContents,		// done
    	FM_MessageBegin,		// done
    	FM_MessageEnd,			// done
    	FM_WriteByte,			// done
    	FM_WriteChar,			// done
    	FM_WriteShort,			// done
    	FM_WriteLong,			// done
    	FM_WriteAngle,			// done
    	FM_WriteCoord,			// done
    	FM_WriteString,			// done
    	FM_WriteEntity,			// done
    	FM_CVarGetFloat,		// done
    	FM_CVarGetString,		// done
    	FM_CVarSetFloat,		// done
    	FM_CVarSetString,		// done
    	FM_FreeEntPrivateData,		// done
    	FM_SzFromIndex,			// done
    	FM_AllocString,			// done
    	FM_RegUserMsg,			// done
    	FM_AnimationAutomove,		// done
    	FM_GetBonePosition,		// void )	(const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );  -- does't work as of 0.20 RC2
    	FM_GetAttachment,		// void	)	(const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles );  -- does't work as of 0.20 RC2
    	FM_SetView,			// done
    	FM_Time,			// done
    	FM_CrosshairAngle,		// done
    	FM_FadeClientVolume,		// done
    	FM_SetClientMaxspeed,		// done
    	FM_CreateFakeClient,		// done
    	FM_RunPlayerMove,		// void )	(edict_t *fakeclient, const float *viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, byte msec ); -- does't work as of 0.20 RC2
    	FM_NumberOfEntities,		// done
    	FM_StaticDecal,			// done
    	FM_PrecacheGeneric,		// done
    	FM_BuildSoundMsg,		// void )	(edict_t *entity, int channel, const char *sample, /*int*/float volume, float attenuation, int fFlags, int pitch, int msg_dest, int msg_type, const float *pOrigin, edict_t *ed);  -- does't work as of 0.20 RC2
    	FM_GetPhysicsKeyValue,		// done
    	FM_SetPhysicsKeyValue,		// done
    	FM_GetPhysicsInfoString,	// done
    	FM_PrecacheEvent,		// done
    	FM_PlaybackEvent,		// done
    	FM_CheckVisibility,		//)		(
    	FM_GetCurrentPlayer,		// done
    	FM_CanSkipPlayer,		// done
    	FM_SetGroupMask,		// done
    	FM_Voice_GetClientListening,	// done
    	FM_Voice_SetClientListening,	// done
    	FM_InfoKeyValue,		// done
    	FM_SetKeyValue,			// done
    	FM_SetClientKeyValue,		// done
    	FM_GetPlayerAuthId,		// done
    	FM_GetPlayerWONId,		// done
    	FM_IsMapValid,			// done
    
    
    	FM_Spawn,			// done
    	FM_Think,			// done
    	FM_Use,				// done
    	FM_Touch,			// done
    	FM_Blocked,			// done
    	FM_KeyValue,			// void )	( edict_t *pentKeyvalue, KeyValueData *pkvd ); -- does't work as of 0.20 RC2
    	FM_SetAbsBox,			// done
    	FM_ClientConnect,		// done
    	
    	FM_ClientDisconnect,		// done
    	FM_ClientKill,			// done
    	FM_ClientPutInServer,		// done
    	FM_ClientCommand,		// done
    
    	FM_ServerDeactivate,		// done
    
    	FM_PlayerPreThink,		// done
    	FM_PlayerPostThink,		// done
    
    	FM_StartFrame,			// done
    	FM_ParmsNewLevel,		// done
    	FM_ParmsChangeLevel,		// done
    
    	 // Returns string describing current .dll.  E.g., TeamFotrress 2, Half-Life
    	FM_GetGameDescription,	 	// done
    
    	// Spectator funcs
    	FM_SpectatorConnect,		// done
    	FM_SpectatorDisconnect,		// done
    	FM_SpectatorThink,		// done
    
    	// Notify game .dll that engine is going to shut down.  Allows mod authors to set a breakpoint.
    	FM_Sys_Error,			// done
    
    	FM_PM_FindTextureType,		// done
    	FM_RegisterEncoders,		// done
    
    	// Enumerates player hulls.  Returns 0 if the hull number doesn't exist, 1 otherwise
    
    	// Create baselines for certain "unplaced" items.
    	FM_CreateInstancedBaseline,	// done 
    	FM_AllowLagCompensation,	// done
    	FM_AlertMessage,		// done		(at_type, message[])
    
    	// NEW_DLL_FUNCTIONS:
    	FM_OnFreeEntPrivateData,
    	FM_GameShutdown,
    	FM_ShouldCollide
    };

Miscellaneous:
  • The method I use above is my own personal tried and true method I've been using. Feel free to look into other methods of blocking attack and manipulating weapon sequences:
    • FM_AddToFullPack
    • FM_CmdStart

Any Karma donations are welcomed!
__________________

My 3D Art: http://k-c-e.deviantart.com/

[img]http://img213.**************/img213/7132/userbar152416mp2.gif[/img]
[img]http://img65.**************/img65/5606/userbar152433ie5.gif[/img]
[img]http://img223.**************/img223/7576/userbar152440yk6.gif[/img]

Last edited by KCE; 10-04-2006 at 22:36.
KCE is offline
v3x
Veteran Member
Join Date: Oct 2004
Location: US
Old 07-12-2006 , 12:00   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #2

Interesting :]
__________________
What am I doing these days? Well, I run my own Rust server. It's heavily modded. If you'd like to join, the ip is 167.114.101.67:28116

I also created a website called Rust Tools. It will calculate and tell you the raw amounts of resources needed to craft items.
v3x is offline
Cheap_Suit
Veteran Member
Join Date: May 2004
Old 07-12-2006 , 15:04   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #3

pimpin...

Thank you! And great job on your ml plugin too!
__________________
HDD fried, failed to backup files. Sorry folks, just don't have free time anymore. This is goodbye.
Cheap_Suit is offline
DevconeS
Member
Join Date: May 2006
Location: Switzerland
Old 07-12-2006 , 20:28   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #4

Quote:
Originally Posted by KCE
Code:
//fakemeta method public PlayerPreThink( id ) {     //Do whatever checks you need to do and whatnot...         if( !is_user_alive(id) )         return FMRES_IGNORED;         //Remove the attack button from their button mask         set_pev( id, pev_button, pev(id,pev_button) & ~IN_ATTACK );     return FMRES_HANDLED; }
Blocking buttons like IN_ATTACK in PreThink isn't very good. It just works for the knife and not that good.

I recommend the use of FM_CmdStart because it causes a better result than in PretThink and you're able to block all the weapon attacks.
Code:
// Put this in plugin init (yes it's for hooking the forward) register_forward(FM_CmdStart,"fwd_CmdStart") // Put this somewhere in the code ;) public fwd_CmdStart(id, uc_handle, seed) {     if(!is_user_alive(id)) return FMRES_IGNORED         new buttons = get_uc(uc_handle,UC_Buttons)     if(buttons & IN_ATTACK) {         buttons &= ~IN_ATTACK         set_uc(uc_handle,UC_Buttons,buttons)     }     return FMRES_HANDLED }

Last edited by DevconeS; 07-12-2006 at 20:38.
DevconeS is offline
KCE
Senior Member
Join Date: Jan 2005
Location: Los Angeles, CA
Old 07-12-2006 , 20:40   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #5

Quote:
Originally Posted by DevconeS
Blocking buttons like IN_ATTACK in PreThink isn't very good. It just works for the knife and not that good.

I recommend the use of FM_CmdStart because it causes a better result than in PretThink and you're able to block all the weapon attacks.
Code:
// Put this in plugin init (yes it's for hooking the forward) register_forward(FM_CmdStart,"fwd_CmdStart") // Put this somewhere in the code ;) public fwd_CmdStart(id, uc_handle, seed) {     if(!is_user_alive(id)) return FMRES_IGNORED         new buttons = get_uc(uc_handle,UC_Buttons)     if(buttons & IN_ATTACK) {         buttons &= ~IN_ATTACK         set_uc(uc_handle,UC_Buttons,buttons)     }     return FMRES_HANDLED }
So far preThink is the tried and true method. There's never one solution to a problem

EDIT: Ok, I've just tried it and it seems to work the same way as preThink? Nothing different...
__________________

My 3D Art: http://k-c-e.deviantart.com/

[img]http://img213.**************/img213/7132/userbar152416mp2.gif[/img]
[img]http://img65.**************/img65/5606/userbar152433ie5.gif[/img]
[img]http://img223.**************/img223/7576/userbar152440yk6.gif[/img]

Last edited by KCE; 07-12-2006 at 20:56.
KCE is offline
Orangutanz
Veteran Member
Join Date: Apr 2006
Old 07-12-2006 , 20:52   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #6

Its more resourceful DevconeS way, since you are getting the change state of the buttons instantly as it happens, whereas prethink you don't.

Last edited by Orangutanz; 07-12-2006 at 21:29.
Orangutanz is offline
DevconeS
Member
Join Date: May 2006
Location: Switzerland
Old 07-12-2006 , 21:02   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #7

Quote:
Originally Posted by KCE
So far preThink is the tried and true method. There's never one solution to a problem

EDIT: Ok, I've just tried it and it seems to work the same way as preThink? Nothing different...
Blocking the knife sounds seems to be working fine, but you see how it trys to animate for a little moment.
Yes I've tested this on CS.
DevconeS is offline
Cheap_Suit
Veteran Member
Join Date: May 2004
Old 07-12-2006 , 22:34   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #8

Function renaming solved the problem, sorry.
__________________
HDD fried, failed to backup files. Sorry folks, just don't have free time anymore. This is goodbye.

Last edited by Cheap_Suit; 07-12-2006 at 22:41.
Cheap_Suit is offline
Obbin
Senior Member
Join Date: Mar 2005
Location: 192.168.1.3
Old 08-21-2006 , 11:37   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #9

Wouldn't it be possible to block the reload animation by checking get_user_buttons and if they are reloading, reset the model sequence to idle?
__________________
Sig(h)!
Obbin is offline
Cheap_Suit
Veteran Member
Join Date: May 2004
Old 10-02-2006 , 00:40   Re: Blocking weapon fire, including client-side sounds/animations
Reply With Quote #10

I mean "trigger" not set or play. I tryed hooking it in FM_CmdStart and also prethink but it doesnt play the animation.
__________________
HDD fried, failed to backup files. Sorry folks, just don't have free time anymore. This is goodbye.
Cheap_Suit is offline
Reply


Thread Tools
Display Modes

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 18:58.


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