AMX Mod X Plugin Approver
|
09-14-2011
, 19:27
Re: [orpheu] Set airaccelerate
|
#24
|
Try that. I've tested with bots and so far it works fine.
The commands are the same as your plugin.
Note : you need Cvar Utilities and the provided signatures (plugin included too).
PHP Code:
#include <amxmodx>
#include <orpheu>
#include <orpheu_memory>
#include <orpheu_stocks>
#include <cvar_util>
#include <fakemeta>
/*
│ PLUGIN
*/
new const PluginName [] = "Custom Player Air Accelerate";
new const PluginVersion [] = "1.3";
new const PluginAuthor [] = "Arkshine";
/*
│ GENERAL
*/
const MaxSlots = 32;
#define FBitSet(%1,%2) ( %1 & ( 1 << ( %2 & 31 ) ) )
#define SetBits(%1,%2) ( %1 |= ( 1 << ( %2 & 31 ) ) )
#define ClearBits(%1,%2) ( %1 &= ~( 1 << ( %2 & 31 ) ) )
new MaxClients;
/*
│ CACHE HANDLING
*/
enum Movevars
{
Float:Gravity,
Float:StopSpeed,
Float:MaxSpeed,
Float:SpectatorMaxSpeed,
Float:Accelerate,
Float:AirAccelerate,
Float:WaterAccelerate,
Float:Friction,
Float:EdgeFriction,
Float:WaterFriction,
Float:EntGravity,
Float:Bounce,
Float:StepSize,
Float:MaxVelocity,
Float:ZMax,
Float:WaveHeigth,
bool:Footsteps,
Float:RollAngle,
Float:RollSpeed,
Float:SkyColorRed,
Float:SkyColorGreen,
Float:SkyColorBlue,
Float:SkyVecX,
Float:SkyVecY,
Float:SkyVecZ,
SkyName[ 16 ],
};
new MoveVarsData[ Movevars ];
/*
│ AIR ACCELERATE HANDLING
*/
new OrpheuStruct:pmove;
new OrpheuFunction:HandleFuncMove;
new OrpheuFunction:HandleFuncAirAccelerate;
new OrpheuFunction:HandleFuncAirMove;
new OrpheuFunction:HandleFuncQueryMovevarsChanged;
new OrpheuFunction:HandleFuncSetMoveVars;
new OrpheuFunction:HandleFuncWriteMovevarsToClient;
new bool:ChangeDetected;
new HasCustomAirAccel;
new Float:PlayerCustomAAValue[ MaxSlots + 1 ];
public plugin_init()
{
register_plugin( PluginName, PluginVersion, PluginAuthor );
handleCommand();
handleCache();
handleForward();
}
public plugin_cfg()
{
MaxClients = get_maxplayers();
}
public client_disconnect( client )
{
ClientCommand_RemoveAA( client, .disconnected = true );
}
/*
│ ┌────────────────────────┐
│ │ INIT FUNCTIONS │
│ └────────────────────────┘
│ → handleCommand()
│ → handleCache()
│ → handleForward()
*/
handleCommand()
{
register_clcmd( "say /setaa50" , "ClientCommand_SetAA50" );
register_clcmd( "say /setaa100", "ClientCommand_SetAA100" );
register_clcmd( "say /rmaa" , "ClientCommand_RemoveAA" );
}
handleCache()
{
// Easily cache the value with Cvar Utilities. ;P
CvarCache( get_cvar_pointer( "sv_gravity" ), CvarType_Float , MoveVarsData[ Gravity ] );
CvarCache( get_cvar_pointer( "sv_stopspeed" ), CvarType_Float , MoveVarsData[ StopSpeed ] );
CvarCache( get_cvar_pointer( "sv_maxspeed" ), CvarType_Float , MoveVarsData[ MaxSpeed ] );
CvarCache( get_cvar_pointer( "sv_spectatormaxspeed" ), CvarType_Float , MoveVarsData[ SpectatorMaxSpeed ] );
CvarCache( get_cvar_pointer( "sv_accelerate" ), CvarType_Float , MoveVarsData[ Accelerate ] );
CvarCache( get_cvar_pointer( "sv_airaccelerate" ), CvarType_Float , MoveVarsData[ AirAccelerate ] );
CvarCache( get_cvar_pointer( "sv_wateraccelerate" ), CvarType_Float , MoveVarsData[ WaterAccelerate ] );
CvarCache( get_cvar_pointer( "sv_friction" ), CvarType_Float , MoveVarsData[ Friction ] );
CvarCache( get_cvar_pointer( "edgefriction" ), CvarType_Float , MoveVarsData[ EdgeFriction ] );
CvarCache( get_cvar_pointer( "sv_waterfriction" ), CvarType_Float , MoveVarsData[ WaterFriction ] );
CvarCache( get_cvar_pointer( "sv_bounce" ), CvarType_Float , MoveVarsData[ Bounce ] );
CvarCache( get_cvar_pointer( "sv_stepsize" ), CvarType_Float , MoveVarsData[ StepSize ] );
CvarCache( get_cvar_pointer( "sv_maxvelocity" ), CvarType_Float , MoveVarsData[ MaxVelocity ] );
CvarCache( get_cvar_pointer( "sv_zmax" ), CvarType_Float , MoveVarsData[ ZMax ] );
CvarCache( get_cvar_pointer( "sv_wateramp" ), CvarType_Float , MoveVarsData[ WaveHeigth ] );
CvarCache( get_cvar_pointer( "mp_footsteps" ), CvarType_Float , MoveVarsData[ Footsteps ] );
CvarCache( get_cvar_pointer( "sv_skycolor_r" ), CvarType_Float , MoveVarsData[ SkyColorBlue ] );
CvarCache( get_cvar_pointer( "sv_skycolor_g" ), CvarType_Float , MoveVarsData[ SkyColorGreen ] );
CvarCache( get_cvar_pointer( "sv_skycolor_b" ), CvarType_Float , MoveVarsData[ SkyColorRed ] );
CvarCache( get_cvar_pointer( "sv_skyvec_x" ), CvarType_Float , MoveVarsData[ SkyVecX ] );
CvarCache( get_cvar_pointer( "sv_skyvec_y" ), CvarType_Float , MoveVarsData[ SkyVecY ] );
CvarCache( get_cvar_pointer( "sv_skyvec_z" ), CvarType_Float , MoveVarsData[ SkyVecZ ] );
CvarCache( get_cvar_pointer( "sv_skyname" ), CvarType_String, MoveVarsData[ SkyName ], charsmax( MoveVarsData[ SkyName ] ) );
// No existing server cvars, hardcoded value.
MoveVarsData[ EntGravity ] = _:1.0;
MoveVarsData[ RollAngle ] = _:0.0;
MoveVarsData[ RollSpeed ] = _:0.0;
}
handleForward()
{
register_forward( FM_ClientConnect, "ClientConnect" );
// Mod.
HandleFuncMove = OrpheuGetDLLFunction( "pfnPM_Move", "PM_Move" );
if( is_linux_server() )
HandleFuncAirMove = OrpheuGetFunction( "PM_AirMove" );
else
HandleFuncAirAccelerate = OrpheuGetFunction( "PM_AirAccelerate" );
// Engine - Main function.
HandleFuncQueryMovevarsChanged = OrpheuGetFunction( "SV_QueryMovevarsChanged" );
{
if( is_linux_server() )
{
HandleFuncSetMoveVars = OrpheuGetFunction( "SV_SetMoveVars" );
HandleFuncWriteMovevarsToClient = OrpheuGetFunction( "SV_WriteMovevarsToClient" );
}
else
{
// Trick to avoid to make signatures.
new const startAddress = OrpheuGetFunctionAddress( HandleFuncQueryMovevarsChanged );
new const numCallsToIgnore = 1;
HandleFuncSetMoveVars = OrpheuCreateFunction( OrpheuGetNextCallAtAddress( startAddress, .number = numCallsToIgnore + 1 ), "SV_SetMoveVars" );
HandleFuncWriteMovevarsToClient = OrpheuCreateFunction( OrpheuGetNextCallAtAddress( startAddress, .number = numCallsToIgnore + 2 ), "SV_WriteMovevarsToClient" );
}
}
}
/*
│ ┌────────────────────┐
│ │ FORWARD HANDLING │
│ └────────────────────┘
│ → updateForward()
*/
updateForward()
{
// Mod.
static OrpheuHook:handleHookMove;
static OrpheuHook:handleHookAirAccelerate;
static OrpheuHook:handleHookAirMovePre;
static OrpheuHook:handleHookAirMovePost;
// Engine.
static OrpheuHook:handleHookQueryMovevarsChanged;
static OrpheuHook:handleHookSetMoveVars;
static OrpheuHook:handleHookWriteMovevarsToClient;
new foundUsers;
static wasFoundUsers;
// Should the forwards be toggled ?
if( ( foundUsers = !!HasCustomAirAccel ) ^ wasFoundUsers )
{
// There are at least one player and the forwards should be registered.
if( foundUsers )
{
// Mod.
handleHookMove = OrpheuRegisterHook( HandleFuncMove, "PM_Move" );
if( is_linux_server() )
{
// Damn. The content of PM_AirAccelerate is integrated in PM_AirMove.
handleHookAirMovePre = OrpheuRegisterHook( HandleFuncAirMove, "PM_AirMove_Pre" , OrpheuHookPre );
handleHookAirMovePost = OrpheuRegisterHook( HandleFuncAirMove, "PM_AirMove_Post", OrpheuHookPost );
}
else
{
// I loves windows.
handleHookAirAccelerate = OrpheuRegisterHook( HandleFuncAirAccelerate, "PM_AirAccelerate" );
}
// Engine.
handleHookQueryMovevarsChanged = OrpheuRegisterHook( HandleFuncQueryMovevarsChanged , "SV_QueryMovevarsChanged_Post", OrpheuHookPost );
handleHookSetMoveVars = OrpheuRegisterHook( HandleFuncSetMoveVars , "SV_SetMoveVars" );
handleHookWriteMovevarsToClient = OrpheuRegisterHook( HandleFuncWriteMovevarsToClient, "SV_WriteMovevarsToClient" );
}
// No more players are using the command, the forwards should be stopped now.
else
{
// Mod.
OrpheuUnregisterHook( handleHookMove );
if( is_linux_server() )
{
OrpheuUnregisterHook( handleHookAirMovePre );
OrpheuUnregisterHook( handleHookAirMovePost );
}
else
{
OrpheuUnregisterHook( handleHookAirAccelerate );
}
// Engine.
OrpheuUnregisterHook( handleHookQueryMovevarsChanged );
OrpheuUnregisterHook( handleHookSetMoveVars );
OrpheuUnregisterHook( handleHookWriteMovevarsToClient );
}
}
wasFoundUsers = foundUsers;
}
/*
│ ┌────────────────────┐
│ │ COMMAND HANDLING │
│ └────────────────────┘
│ → ClientCommand_SetAA50()
│ └ setAA()
│ → ClientCommand_SetAA100()
│ └ setAA()
│ → ClientCommand_RemoveAA()
*/
public ClientCommand_SetAA50( const client )
{
setAA( client, 50.0 );
}
public ClientCommand_SetAA100( const client )
{
setAA( client, 100.0 );
}
public ClientCommand_RemoveAA( const client, const bool:disconnected )
{
// You stop using the custom air acceleration.
ClearBits( HasCustomAirAccel, client );
// Stops the forwards if no more users.
updateForward();
// Update the client right away with the original value.
if( !disconnected )
{
WriteMovevarsToClient( client );
}
}
setAA( const player, const Float:aa )
{
// Save the player's custom air accelerate value.
PlayerCustomAAValue[ player ] = aa;
// Allowed to use a custom air acceleration value.
SetBits( HasCustomAirAccel, player );
// Register the forwards.
updateForward();
// Update the client with the new value, otherwise prediction will be off and resulting lag.
WriteMovevarsToClient( player );
}
/*
│ ┌───────────────────────────┐
│ │ AIR ACCELERATE HANDLING │
│ └───────────────────────────┘
│ → PM_Move()
│ → PM_AirMove_Pre()
│ → PM_AirMove_Post()
│ → PM_AirAccelerate()
│ → SV_SetMoveVars()
│ → SV_WriteMovevarsToClient()
│ → SV_QueryMovevarsChanged_Post()
│ └ WriteMovevarsToClient()
│ ┌ checkConnectingClient()
│ └ sendNewMoveVars()
*/
public PM_Move( OrpheuStruct:ppmove, const server )
{
pmove = ppmove;
}
public PM_AirMove_Pre()
{
new player = OrpheuGetStructMember( pmove, "player_index" ) + 1;
if( FBitSet( HasCustomAirAccel, player ) && is_user_alive( player ) )
{
// Linux-specific.
// We modify on-the-fly pmove->movevars->airaccelerate to our custom value.
OrpheuSetStructMember( OrpheuStruct:OrpheuGetStructMember( pmove, "movevars" ), "airaccelerate", PlayerCustomAAValue[ player ] );
}
}
public PM_AirMove_Post()
{
new player = OrpheuGetStructMember( pmove, "player_index" ) + 1;
if( FBitSet( HasCustomAirAccel, player ) && is_user_alive( player ) )
{
// Linux-specific.
// Then we set back the current sv_airaccelerate value to avoid to trigger change.
OrpheuSetStructMember( OrpheuStruct:OrpheuGetStructMember( pmove, "movevars" ), "airaccelerate", MoveVarsData[ AirAccelerate ] );
}
}
public PM_AirAccelerate( const Float:wishdir[3], const Float:wishspeed, const Float:accel )
{
new player = OrpheuGetStructMember( pmove, "player_index" ) + 1;
if( FBitSet( HasCustomAirAccel, player ) && is_user_alive( player ) )
{
// pmove->movevars->airaccelerate is passed as 'accel' param.
// More simple to modify directly the function where the movevars is used.
// Also, it would be called only when you are in the air.
OrpheuSetParam( 3, PlayerCustomAAValue[ player ] );
}
}
// Order of calls.
// SV_QueryMovevarsChanged -> SV_SetMoveVars -> SV_WriteMovevarsToClient
public SV_SetMoveVars()
{
// Called from SV_QueryMovevarsChanged
// This function overwrites the server movevars values with the value of the cvars.
// We use just this function to detect a change since the main function does not return a value.
ChangeDetected = true;
}
public OrpheuHookReturn:SV_WriteMovevarsToClient()
{
// This function sends the message SVC_NEWMOVEVARS (internally) using the movevars values.
// When a change is detected, this function is called for all players to update them.
// Since the param passed is not the player's index and to have a full control,
// We simply blocks the call all the time and sending manually a message when needed after.
return OrpheuSupercede;
}
public SV_QueryMovevarsChanged_Post()
{
// This function is called per frame to detect if there is at least one change between
// the movevars values and the corresponding server cvars values.
// When a change is detected, it calls SV_SetMoveVars to update all the server movevars,
// then call SV_WriteMovevarsToClient to update each clients.
// Here, we hook the function as post because since we block the update on the client, we
// need to update manually the client. It allows us to put conditions and sending per player
// and will handle the case where you use sv_ cvar in the console.
if( ChangeDetected )
{
ChangeDetected = false;
WriteMovevarsToClient( .client = 0 );
}
}
public WriteMovevarsToClient( const client )
{
// Time to update the client.
// Such message is originally sent one time at player's connection,
new playerToUpdate = client ? client : checkConnectingClient();
if( playerToUpdate )
{
sendNewMoveVars( playerToUpdate );
}
else
{
for( new i = 1; i <= MaxClients; i++ )
{
if( is_user_connected( i ) && !is_user_bot( i ) )
{
sendNewMoveVars( i );
}
}
}
}
sendNewMoveVars( const client )
{
message_begin( MSG_ONE, SVC_NEWMOVEVARS, .player = client );
{
write_long( _:MoveVarsData[ Gravity ] );
write_long( _:MoveVarsData[ StopSpeed ] );
write_long( _:MoveVarsData[ MaxSpeed ] );
write_long( _:MoveVarsData[ SpectatorMaxSpeed ] );
write_long( _:MoveVarsData[ Accelerate ] );
write_long( _:( FBitSet( HasCustomAirAccel, client ) ? PlayerCustomAAValue[ client ] : MoveVarsData[ AirAccelerate ] ) );
write_long( _:MoveVarsData[ WaterAccelerate ] );
write_long( _:MoveVarsData[ Friction ] );
write_long( _:MoveVarsData[ EdgeFriction ] );
write_long( _:MoveVarsData[ WaterFriction ] );
write_long( _:MoveVarsData[ EntGravity ] );
write_long( _:MoveVarsData[ Bounce ] );
write_long( _:MoveVarsData[ StepSize ] );
write_long( _:MoveVarsData[ MaxVelocity ] );
write_long( _:MoveVarsData[ ZMax ] );
write_long( _:MoveVarsData[ WaveHeigth ] );
write_byte( !!MoveVarsData[ Footsteps ] );
write_long( _:MoveVarsData[ RollAngle ] );
write_long( _:MoveVarsData[ RollSpeed ] );
write_long( _:MoveVarsData[ SkyColorBlue ] );
write_long( _:MoveVarsData[ SkyColorGreen ] );
write_long( _:MoveVarsData[ SkyColorRed ] );
write_long( _:MoveVarsData[ SkyVecX ] );
write_long( _:MoveVarsData[ SkyVecY ] );
write_long( _:MoveVarsData[ SkyVecZ ] );
write_string( MoveVarsData[ SkyName ] );
}
message_end();
}
checkConnectingClient()
{
for( new i = 1; i <= MaxClients; i++ )
{
if( is_user_connecting( i ) )
{
return i;
}
}
return 0;
}
/*
│ ┌─────────────────┐
│ │ USEFUL STOCKS │
│ └─────────────────┘
│ → getEngineBuild()
*/
stock getEngineBuild()
{
new version[ 32 ];
get_pcvar_string( get_cvar_pointer( "sv_version" ), version, charsmax( version ) );
new length = strlen( version );
while( version[ --length ] != ',' ) {}
return str_to_num( version[ length + 1 ] );
}
Unzip and extract in your amxmodx/ directory.
Tell me If it works as expected.
__________________
Last edited by Arkshine; 11-19-2011 at 04:57.
Reason: Updated to 1.3
|
|