Code:
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
// the speed player will travel towards surface
#define JUMP_SPEED 1000.0
// maximum distance player can be from the surface for the jump to work
#define REQUIRED_SURFACE_DISTANCE 100.0
// the amount of time player should be finished with the jump
// speed = distance / time, speed * time = distance, time = distance / time
#define FINISH_TIME (REQUIRED_SURFACE_DISTANCE / JUMP_SPEED)
// the delay between jump uses
// the delay MUST include the "FINISH_TIME" #define
#define JUMP_DELAY (FINISH_TIME + 5.0)
new bool:g_alive[33];
new bool:g_jumping[33];
new Float:g_jump_wait[33];
public plugin_init()
{
register_plugin("Dolphin Jumping", "0.1", "Exolent");
register_event("ResetHUD", "EventResetHud", "be");
register_event("DeathMsg", "EventDeathMsg", "a");
register_forward(FM_CmdStart, "FwdCmdStart");
register_forward(FM_PlayerPreThink, "FwdPlayerPreThink");
}
public client_disconnect(client)
{
g_alive[client] = false;
g_jumping[client] = false;
g_jump_wait[client] = 0.0;
}
public EventResetHud(client)
{
g_alive[client] = bool:is_user_alive(client);
}
public EventDeathMsg()
{
new client = read_data(2);
g_alive[client] = false;
g_jumping[client] = false;
g_jump_wait[client] = 0.0;
}
public FwdCmdStart(client, uc_handle, seed)
{
if( !g_alive[client] || g_jumping[client] || pev(client, pev_waterlevel) != 3 ) return;
new button = get_uc(uc_handle, UC_Buttons);
new oldbuttons = pev(client, pev_oldbuttons);
if( !((button & IN_DUCK) && (oldbuttons & IN_DUCK)
&& (button & IN_JUMP) && !(oldbuttons & IN_JUMP)) ) return;
new Float:gametime = get_gametime();
if( gametime < g_jump_wait[client] ) return;
static Float:origin[3], Float:maxs[3];
pev(client, pev_origin, origin);
pev(client, pev_maxs, maxs);
origin[2] += REQUIRED_SURFACE_DISTANCE - maxs[2];
if( engfunc(EngFunc_PointContents, origin) != CONTENTS_EMPTY )
{
// punish player for trying from too deep by waiting 1 second before trying again?
// comment the line below to remove this feature
g_jump_wait[client] = gametime + 1.0;
return;
}
g_jumping[client] = true;
g_jump_wait[client] = gametime + JUMP_DELAY;
}
public FwdPlayerPreThink(client)
{
if( !g_jumping[client] ) return;
if( get_gametime() >= g_jump_wait[client] )
{
g_jumping[client] = false;
g_jump_wait[client] = 0.0;
return;
}
static Float:origin[3];
pev(client, pev_origin, origin);
static Float:maxs[3];
pev(client, pev_maxs, maxs);
origin[2] -= maxs[2];
if( engfunc(EngFunc_PointContents, origin) == CONTENTS_WATER )
{
// feet are touching water, so keep flying
set_pev(client, pev_movetype, MOVETYPE_FLY);
}
origin[2] += (maxs[2] * 2.0);
if( engfunc(EngFunc_PointContents, origin) == CONTENTS_WATER )
{
// head is still underwater, so keep the speed
static Float:velocity[3];
velocity[2] = JUMP_SPEED;
set_pev(client, pev_velocity, velocity);
}
}