the plugin gives not an error or something like that its working and the name of the bot is RECORD BOT
but its not moving or it not shows the worldrecords for some reason can someone help?
Code:
/*
*
* KZ:Bots
* by: Garey
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <amxmodx>
#include <curl>
#include <amxxarch>
#include <hamsandwich>
#include <fakemeta_util>
#define PLUGIN "KZ:Bot"
#define VERSION "2.0 Beta"
#define AUTHOR "Garey"
#pragma dynamic 131068 // without this line will probly crash the server
#define MAX_SOURCES 16
enum FWrite
{
FW_NONE = 0,
FW_DELETESOURCE = (1<<0),
FW_CANOVERRIDE = (1<<1)
}
new const rec_foldername[10] = "kz_bots";
new const rec_recorder[] = "ent_recorder";
new const rec_demoparser[] = "dem_think";
new Array:record_info[33];
new global_bot;
enum source_data
{
source_id,
source_type,
source_name[32],
source_time[32],
source_path[128],
source_startframe,
Float:source_starttime,
Float:source_stoptime,
Array:source_array
}
new sources_num = 0;
new bot_sources[MAX_SOURCES][source_data]
enum _:MODES
{
MODE_CYCLE,
MODE_USE,
MODE_WAIT
}
new bot_modes[MODES][] =
{
"Cycle Run",
"Restart on USE",
"Restart on USE + Wait on distance"
}
new bool:plr_botnamed[33];
new plr_sound[33];
new plr_mode[33];
new plr_source[33];
new plr_frame_it[33];
new plr_jump[33] = {300, ... };
new plr_saverun_time[32][32];
new bool:plr_delayed_save[33];
new Float:plr_delayed_timer[33];
new bool:plr_playback[33];
new bool:bot_inrestart[33];
new Float:bot_restarttime[33];
new bool:is_recording[33];
enum frame_data
{
Float:frame_origin[3],
Float:frame_angles[3],
Float:frame_velocity[3],
frame_buttons,
Float:frame_time
}
new ghost_data[33][frame_data];
new maxplayers;
new cvar_mode;
new cvar_speed;
new cvar_keys;
new map_records_dir[128];
new Trie:start_buttons;
new Trie:stop_buttons
new step_sounds[4]
/************************************************
* *
* SOURCE CODE START *
* *
*************************************************/
public plugin_precache()
{
step_sounds[0] = precache_sound("player/pl_step1.wav");
step_sounds[1] = precache_sound("player/pl_step2.wav");
step_sounds[2] = precache_sound("player/pl_step3.wav");
step_sounds[3] = precache_sound("player/pl_step4.wav");
}
public plugin_natives()
{
register_native("save_run", "native_save_run")
register_native("pause_run", "native_pause_run")
register_native("unpause_run", "native_unpause_run")
register_native("reset_run", "native_reset_run")
}
public plugin_cfg()
{
new record_list[128]
new record_list_cosy[128]
get_localinfo( "amxx_datadir", map_records_dir, charsmax( map_records_dir ) );
format(map_records_dir, charsmax(map_records_dir), "%s/%s", map_records_dir,rec_foldername)
format(record_list, charsmax(record_list), "%s/record_list.txt", map_records_dir);
format(record_list_cosy, charsmax(record_list_cosy), "%s/record_list2.txt", map_records_dir);
new sz_mapname[64];
get_mapname(sz_mapname, 63);
if(!dir_exists(map_records_dir))
{
mkdir(map_records_dir);
}
format(map_records_dir, charsmax(map_records_dir), "%s/%s", map_records_dir,sz_mapname)
if(!dir_exists(map_records_dir))
{
mkdir(map_records_dir)
}
new szFileName[64]
new hDir = open_dir(map_records_dir, szFileName, charsmax(szFileName))
do
{
if(equal(szFileName, "..") || equal(szFileName, "."))
continue
new len = strlen(szFileName);
if(!equal(szFileName[len-3], "rec"))
{
continue;
}
new path[128]
format(path, 128, "%s/%s", map_records_dir, szFileName);
load_run(path);
}
while ( next_file( hDir, szFileName, charsmax( szFileName ) ) )
close_dir(hDir)
curl_download_file( record_list, "https://xtreme-jumps.eu/demos.txt", "", "");
curl_download_file( record_list_cosy, "https://cosy-climbing.net/demoz.txt", "", "");
set_task(3.0, "create_bot");
}
public create_bot()
{
global_bot = makebot("Record Bot");
}
public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR);
register_clcmd( "kzbot_settings","kzbot_settings" );
register_clcmd( "say /bot","kzbot_menu" );
register_clcmd( "load_demo" ,"process_demo" );
start_buttons = TrieCreate();
stop_buttons = TrieCreate();
new const start_names[][] = { "counter_start", "clockstartbutton", "firsttimerelay", "gogogo", "startcounter", "multi_start" }
new const stop_names[][] = { "counter_off", "clockstopbutton", "clockstop", "stop_counter", "stopcounter", "multi_stop" }
for(new i = 0; i < sizeof(start_names); i++)
{
TrieSetCell(start_buttons, start_names[i], 1)
}
for(new i = 0; i < sizeof(stop_names); i++)
{
TrieSetCell(stop_buttons, stop_names[i], 1)
}
RegisterHam( Ham_Use, "func_button", "fw_use", 0);
register_forward(FM_ClientUserInfoChanged, "fw_clientinfochanged", 1);
register_forward(FM_AddToFullPack,"fw_addtofullpack", 1)
register_forward(FM_UpdateClientData, "fw_updateclientdata", 1)
register_forward(FM_CheckVisibility,"fw_checkvisibility")
cvar_mode = register_cvar("kzbot_on", "1");
cvar_keys = register_cvar("kzbot_keys", "1");
cvar_speed = register_cvar("kzbot_speed", "1");
new ent = fm_create_entity( "info_target" );
if ( ent )
{
set_pev( ent, pev_classname, rec_recorder );
set_pev( ent, pev_nextthink, get_gametime() + 0.01 );
RegisterHam( Ham_Think, "info_target", "forward_think", 1 );
}
maxplayers = get_maxplayers();
for ( new i = 1; i <= maxplayers; i++ )
{
record_info[i] = ArrayCreate( frame_data );
}
for ( new i = 0; i < MAX_SOURCES; i++)
{
bot_sources[i][source_array] = _:ArrayCreate( frame_data );
}
}
public fw_clientinfochanged(id, buffer)
{
if(id == global_bot)
{
arrayset(plr_botnamed, false, 32);
}
}
public client_putinserver(id)
{
plr_playback[id] = true;
plr_source[id] = 0;
plr_frame_it[id] = 0;
plr_botnamed[id] = false;
}
public client_disconnect(id)
{
if(plr_delayed_save[id])
{
save_run(id, plr_saverun_time[id], false);
plr_delayed_save[id] = false;
}
}
public fw_prethink(id)
{
static Float:oldorigin[33][3];
static Float:oldangles[33][3];
static oldbuttons[33];
static damaged_frames[33];
new bool:dontstep = false;
if(id == global_bot)
{
return FMRES_IGNORED;
}
if(!is_user_connected(global_bot))
{
plr_botnamed[id] = false;
}
else if(!is_user_alive(global_bot))
{
plr_botnamed[id] = false;
}
if(is_user_connected(id) && !plr_botnamed[id] && global_bot && sources_num && plr_frame_it[id])
{
update_sourcename(id);
plr_botnamed[id] = true;
}
if(bot_inrestart[id])
{
if(get_gametime() > bot_restarttime[id])
{
bot_inrestart[id] = false;
plr_frame_it[id] = 0;
}
}
if(bot_sources[plr_source[id]][source_stoptime] && plr_frame_it[id] > 100 && ghost_data[id][frame_time] >= bot_sources[plr_source[id]][source_stoptime])
{
if(!bot_inrestart[id])
{
bot_inrestart[id] = true;
bot_restarttime[id] = get_gametime()+0.7;
}
}
if(plr_playback[id])
{
if(plr_mode[id] == MODE_WAIT )
{
new Float:origin[2][3];
pev(id, pev_origin, origin[0]);
xs_vec_copy(ghost_data[id][frame_origin], origin[1]);
if(get_distance_f(origin[0], origin[1]) < 200.0)
{
plr_frame_it[id]++;
}
else
{
dontstep = true;
}
}
else
plr_frame_it[id]++;
}
else
{
dontstep = true;
}
if(!bot_sources[plr_source[id]][source_array] || !ArraySize(bot_sources[plr_source[id]][source_array]))
{
return FMRES_IGNORED
}
if(plr_frame_it[id] > ArraySize(bot_sources[plr_source[id]][source_array])-1)
{
if(!bot_inrestart[id])
{
bot_inrestart[id] = true;
bot_restarttime[id] = get_gametime()+0.7;
get_gametime()
}
plr_frame_it[id] = ArraySize(bot_sources[plr_source[id]][source_array])-1;
return FMRES_IGNORED
}
new Float:vel[3], Float:origins[3];
ArrayGetArray(bot_sources[plr_source[id]][source_array], plr_frame_it[id], ghost_data[id]);
new onground = ghost_data[id][frame_velocity][2] == 0.0 || ghost_data[id][frame_velocity][2] == 260.25 ? true : false
xs_vec_copy(ghost_data[id][frame_origin], origins);
xs_vec_copy(ghost_data[id][frame_velocity], vel);
if(ghost_data[id][frame_buttons] & IN_USE && ~oldbuttons[id] & IN_USE)
{
if(!bot_sources[plr_source[id]][source_starttime] || !bot_sources[plr_source[id]][source_stoptime])
{
CheckButton(id);
}
}
if(get_distance_f(oldorigin[id], origins) > 100.0)
{
damaged_frames[id]++;
}
else
{
xs_vec_copy(origins, oldorigin[id]);
xs_vec_copy(ghost_data[id][frame_angles], oldangles[id]);
damaged_frames[id] = 0;
}
if(damaged_frames[id] > 10)
{
damaged_frames[id] = 0;
xs_vec_copy(origins, oldorigin[id]);
xs_vec_copy(ghost_data[id][frame_angles], oldangles[id]);
}
xs_vec_copy(oldorigin[id], ghost_data[id][frame_origin]);
xs_vec_copy(oldangles[id], ghost_data[id][frame_angles]);
if(get_distance_f(origins, oldorigin[id]) < 100.0 && !damaged_frames[id])
{
xs_vec_copy(ghost_data[id][frame_origin], oldorigin[id]);
xs_vec_copy(ghost_data[id][frame_angles], oldangles[id]);
}
vel[2] = 0.0;
if(!dontstep)
{
if(onground && (vector_length(vel) > 120.0))
{
if(ghost_data[id][frame_buttons] & IN_JUMP && ~oldbuttons[id] & IN_JUMP && plr_sound[id] < 200)
{
plr_sound[id] = 0;
}
if(pev(id, pev_groupinfo) && pev(id, pev_iuser2) == global_bot)
{
playback_sound(id, origins);
}
else if(!pev(id, pev_groupinfo))
{
playback_sound(id, origins);
}
}
}
oldbuttons[id] = ghost_data[id][frame_buttons];
plr_sound[id] -= 10;
return FMRES_IGNORED
}
public fw_checkvisibility(id,pset)
{
forward_return(FMV_CELL, 1);
return FMRES_SUPERCEDE;
}
public fw_updateclientdata(id, sendweapons, cd_handle )
{
if(id == global_bot)
return FMRES_IGNORED;
new ent = pev(id, pev_iuser2);
if(!ent)
return FMRES_IGNORED;
if((global_bot == ent && sources_num) && (ArraySize(bot_sources[plr_source[id]][source_array]) > plr_frame_it[id]))
{
set_cd(cd_handle, CD_Origin, ghost_data[id][frame_origin]);
set_cd(cd_handle, CD_iUser1, pev(id, pev_iuser1));
set_cd(cd_handle, CD_iUser2, ent);
set_cd(cd_handle, CD_Velocity, ghost_data[id][frame_velocity]);
if(ghost_data[id][frame_buttons] & IN_DUCK)
set_cd(cd_handle, CD_ViewOfs, Float:{0.0, 0.0, 12.0});
else
set_cd(cd_handle, CD_ViewOfs, Float:{0.0, 0.0, 17.0});
static sz_time[12];
static Float:ftime
if(bot_sources[plr_source[id]][source_stoptime] && plr_frame_it[id] > 100 && ghost_data[id][frame_time] >= bot_sources[plr_source[id]][source_stoptime])
{
ftime = bot_sources[plr_source[id]][source_stoptime]-bot_sources[plr_source[id]][source_starttime];
if(!bot_inrestart[id])
{
bot_inrestart[id] = true;
bot_restarttime[id] = get_gametime()+0.7;
}
}
else
{
ftime = ghost_data[id][frame_time]-bot_sources[plr_source[id]][source_starttime];
}
fnConvertTime( ftime, sz_time, charsmax( sz_time ) );
if(ftime > 0.0)
{
client_print(id, print_center, "[ %.2s:%.2s.%.2s ]", sz_time, sz_time[2], sz_time[5]);
}
else
client_print(id, print_center, "[ PRE-RECORD ]");
if(get_pcvar_num(cvar_speed))
{
new Float:vel[3];
xs_vec_copy(ghost_data[id][frame_velocity], vel);
vel[2] = 0.0
set_hudmessage( 255, 255, 225, -1.0, 0.83, 0, 0.0, 0.05, 0.0, 0.0, 2);
show_hudmessage(id, "%0.f units", vector_length(vel));
}
if(get_pcvar_num(cvar_keys))
{
new b = ghost_data[id][frame_buttons];
set_hudmessage(255, 255, 225, -1.0, 0.490, 0, 0.0, 0.05, 0.0, 0.0, 4);
show_hudmessage(id, " %s^n %s %s^n %s^n%s^n%s",
b & IN_FORWARD ? "W" : " ",
b & IN_MOVELEFT ? "A" : " ",
b & IN_MOVERIGHT ? "D" : " ",
b & IN_BACK ? "S" : " ",
b & IN_JUMP ? "JUMP" : " ",
b & IN_DUCK ? "DUCK" : " ");
}
return FMRES_SUPERCEDE;
}
return FMRES_IGNORED;
}
public fw_addtofullpack(es_handle,e,ent,host,hostflags,player,pSet)
{
if(global_bot == host)
{
return FMRES_IGNORED;
}
if(player)
{
if(ArraySize(bot_sources[plr_source[host]][source_array]) > plr_frame_it[host])
if(global_bot == ent && sources_num)
{
new Float:origin[2][3];
pev(host, pev_origin, origin[0]);
xs_vec_copy(ghost_data[host][frame_origin], origin[1]);
new spec = pev(host, pev_iuser2);
if(spec && spec != ent)
{
ghost_data[host] = ghost_data[spec];
}
set_es(es_handle, ES_Velocity, ghost_data[host][frame_velocity]);
ghost_data[host][frame_angles][0] /= -3.0;
new bool:onground = ghost_data[host][frame_velocity][2] == 0.0 ? true : false
animate_legs(es_handle, ghost_data[host][frame_buttons], onground);
set_es(es_handle, ES_Angles, ghost_data[host][frame_angles]);
set_es(es_handle, ES_Origin, ghost_data[host][frame_origin]);
set_es(es_handle, ES_Solid, SOLID_NOT);
// fix ugly sequence
set_es(es_handle, ES_Sequence , 75);
set_es(es_handle, ES_RenderMode, kRenderTransAdd);
set_es(es_handle, ES_RenderFx, kRenderFxSolidFast, 0);
set_es(es_handle, ES_RenderAmt, floatround(get_distance_f(origin[0], origin[1]) * 255.0 / 360.0, floatround_floor));
return FMRES_SUPERCEDE;
}
}
return FMRES_IGNORED;
}
public fw_use(ent, id)
{
if(!pev_valid(id) || id > maxplayers)
{
return HAM_IGNORED;
}
new target[32]
pev(ent, pev_target, target, charsmax(target))
new bool:start_timer = false;
new bool:stop_timer = false;
if(TrieKeyExists(start_buttons, target))
{
start_timer = true;
}
else if(TrieKeyExists(stop_buttons, target))
{
stop_timer = true;
}
if(id == global_bot)
{
if(start_timer && !bot_sources[plr_source[id]][source_starttime])
{
bot_sources[plr_source[id]][source_starttime] = _:ghost_data[id][frame_time];
bot_sources[plr_source[id]][source_startframe] = plr_frame_it[id];
}
else if(stop_timer && !bot_sources[plr_source[id]][source_stoptime])
{
bot_sources[plr_source[id]][source_stoptime] = _:ghost_data[id][frame_time];
}
return HAM_SUPERCEDE;
}
if(start_timer && plr_mode[id] >= MODE_USE)
{
plr_frame_it[id] = bot_sources[plr_source[id]][source_startframe];
}
return HAM_IGNORED;
}
/************************************************
* *
* RECORDING & PLAYBACK ARRAYS SECTION *
* *
*************************************************/
#define NUM_THREADS 256
public forward_think( ent )
{
static classname[64]
static si;
pev(ent, pev_classname, classname, 63);
if ( equal( classname, rec_demoparser ) )
{
new file = pev(ent, pev_iuser1);
new source_index = pev(ent, pev_iuser2);
if(!file)
{
set_pev( ent, pev_flags, pev(ent, pev_flags) | FL_KILLME);
return FMRES_IGNORED;
}
if(si != source_index)
{
si = source_index;
}
new bool:Finished;
if(!Finished)
{
for(new i = 0; i < NUM_THREADS; i++)
{
if(read_frames(file, bot_sources[source_index][source_array]))
{
Finished = true;
break;
}
}
}
if(Finished)
{
new filename[64]
DecodeText(pev(ent, pev_iuser3), filename, charsmax(filename))
fclose( file );
new demo_time[32]
demo_time = bot_sources[source_index][source_time]
bot_sources[source_index][source_type] = 1;
save_run(source_index, demo_time, true)
set_pev(ent, pev_iuser1, 0);
set_pev( ent, pev_flags, pev(ent, pev_flags) | FL_KILLME);
}
else
{
set_pev( ent, pev_nextthink, get_gametime() + 0.001 )
}
return FMRES_IGNORED;
}
else if(equal(classname, rec_recorder))
{
new Float:nextthink = 0.01;
if(!get_pcvar_num(cvar_mode))
return FMRES_IGNORED;
else
{
static players[32], inum;
get_players( players, inum );
if(global_bot && inum == 1)
{
set_pev( ent, pev_nextthink, get_gametime()+nextthink);
return FMRES_IGNORED;
}
for ( new i = 0; i < inum; i++ )
{
new id = players[i];
if(global_bot == id)
{
set_pev(id, pev_solid, SOLID_NOT)
dllfunc(DLLFunc_PlayerPreThink, id);
dllfunc(DLLFunc_PlayerPostThink, id);
dllfunc(DLLFunc_UpdateClientData, id);
set_pev(id, pev_solid, SOLID_SLIDEBOX)
set_pev(id, pev_deadflag, DEAD_NO);
set_pev(id, pev_health, 100.0);
}
else
{
if(global_bot)
fw_prethink(id);
if(is_recording[id] || plr_delayed_save[id])
{
if(plr_delayed_save[id])
{
if(get_gametime() > plr_delayed_timer[id])
{
plr_delayed_save[id] = false;
save_run(id, plr_saverun_time[id], false);
}
}
player_record( id )
}
}
}
}
set_pev( ent, pev_nextthink, get_gametime()+nextthink);
}
return FMRES_IGNORED;
}
public CheckButton( id )
{
static ent = -1;
static Float:origin[3];
xs_vec_copy(ghost_data[id][frame_origin], origin);
while ( (ent = fm_find_ent_in_sphere( ent, origin, 100.0 ) ) != 0 )
{
new classname[32];
pev( ent, pev_classname, classname, charsmax( classname ) );
if ( equal( classname, "func_button" ) )
{
new Float:eorigin[3];
fm_get_brush_entity_origin( ent, eorigin );
static target[32];
pev( ent, pev_target, target, 31 );
if(global_bot)
{
if (!bot_sources[plr_source[id]][source_starttime] && TrieKeyExists( start_buttons, target ) )
{
bot_findbuttons(id, global_bot)
}
if (!bot_sources[plr_source[id]][source_stoptime] && TrieKeyExists( stop_buttons, target ) )
{
bot_findbuttons(id, global_bot)
}
}
}
}
}
public bot_findbuttons(id, bot)
{
plr_source[bot] = plr_source[id];
plr_frame_it[bot] = plr_frame_it[id];
ghost_data[bot][frame_time] = _:ghost_data[id][frame_time];
set_pev(bot, pev_origin, ghost_data[id][frame_origin]);
set_pev(bot, pev_button, ghost_data[id][frame_buttons]);
set_pev(bot, pev_movetype, MOVETYPE_WALK);
set_pev(bot, pev_v_angle, ghost_data[id][frame_angles]);
set_pev(bot, pev_angles, ghost_data[id][frame_angles]);
set_pev(bot, pev_fixangle, 1);
engfunc( EngFunc_RunPlayerMove, bot, ghost_data[id][frame_angles], ghost_data[id][frame_velocity][0], ghost_data[id][frame_velocity][1], ghost_data[id][frame_velocity][2], 0, 0, 10);
engfunc( EngFunc_RunPlayerMove, bot, ghost_data[id][frame_angles], ghost_data[id][frame_velocity][0], ghost_data[id][frame_velocity][1], ghost_data[id][frame_velocity][2], IN_USE, 0,10);
}
public player_record( id )
{
static temp_data[frame_data];
temp_data[frame_buttons] = pev(id, pev_button);
pev(id, pev_origin, temp_data[frame_origin]);
pev(id, pev_v_angle, temp_data[frame_angles]);
pev(id, pev_velocity, temp_data[frame_velocity]);
temp_data[frame_time] = _:get_gametime();
ArrayPushArray(record_info[id], temp_data);
}
/************************************************
* *
* DEMO PARSING SECTION *
* *
*************************************************/
/*
Function:
read_demo_header
Description:
Read demo header file from given file pointer
Comment:
There will be magic numbers, i don't wanna create defines for this because i use this only in this function and only for jump offsets in file
If you wanna know what this numbers means, check old WRBot or C++ Project DemTools by Yalter
*/
stock bool:read_demo_header( file )
{
static temp, entries;
fseek( file, 8, SEEK_SET );
fread( file, temp, BLOCK_INT );
if ( temp != 5 )
{
return false;
}
fread( file, temp, BLOCK_INT );
if ( temp != 48 )
{
return false;
}
fseek( file, 260, SEEK_CUR );
fseek( file, 260, SEEK_CUR );
fseek( file, BLOCK_INT, SEEK_CUR );
fread( file, temp, BLOCK_INT );
fseek( file, temp, SEEK_SET );
fread( file, entries, BLOCK_INT );
for ( new i = 0; i < entries; i++ )
{
fseek( file, BLOCK_INT, SEEK_CUR );
fseek( file, 64, SEEK_CUR );
fseek( file, BLOCK_INT, SEEK_CUR );
fseek( file, BLOCK_INT, SEEK_CUR );
fseek( file, BLOCK_INT, SEEK_CUR );
fseek( file, BLOCK_INT, SEEK_CUR );
fread( file, temp, BLOCK_INT );
fseek( file, BLOCK_INT, SEEK_CUR );
}
fseek( file, temp, SEEK_SET );
return true;
}
/*
Function:
read_frame_header
Description:
Read frame header
Comment:
There will be magic numbers, i don't wanna create defines for this because i use this only in this function and only for jump offsets in file
If you wanna know what this numbers means, check old WRBot or C++ Project DemTools by Yalter
*/
public read_frame_header( file, &Float:gametime)
{
static type;
fread( file, type, BLOCK_BYTE );
fread( file, _:gametime, BLOCK_INT );
fseek( file, 4, SEEK_CUR);
return(type);
}
/*
Function:
read_frames
Description:
Read frames and push it to array
Comment:
There will be magic numbers, i don't wanna create defines for this because i use this only in this function and only for jump offsets in file
If you wanna know what this numbers means, check old WRBot or C++ Project DemTools by Yalter
*/
public read_frames( file, Array:array_to )
{
new temp_data[frame_data];
//if ( !feof( file ) )
{
new Float:gametime;
new type = read_frame_header( file, gametime );
new bool:breakme;
switch ( type )
{
case 0:
{
}
case 1:
{
static length;
fseek( file, 84, SEEK_CUR );
//fread( file, _:temp_data[frame_onground], BLOCK_INT );
fseek( file, 8, SEEK_CUR );
//fseek( file, 92, SEEK_CUR );
fread( file, _:temp_data[frame_velocity][0], BLOCK_INT );
fread( file, _:temp_data[frame_velocity][1], BLOCK_INT );
fread( file, _:temp_data[frame_velocity][2], BLOCK_INT );
for ( new i = 0; i < 3; ++i )
fread( file, _:temp_data[frame_origin][i], BLOCK_INT )
fseek( file, 124, SEEK_CUR );
fread( file, _:temp_data[frame_angles][0], BLOCK_INT );
fread( file, _:temp_data[frame_angles][1], BLOCK_INT );
fread( file, _:temp_data[frame_angles][2], BLOCK_INT );
fseek( file, 14, SEEK_CUR );
fread( file, temp_data[frame_buttons], BLOCK_SHORT );
fseek( file, 196, SEEK_CUR );
fread( file, length, BLOCK_INT );
fseek( file, length, SEEK_CUR );
}
case 2:
{
}
case 3:
{
fseek( file, 64, SEEK_CUR);
}
case 4:
{
fseek( file, 32, SEEK_CUR );
}
case 5:
{
breakme = true;
}
case 6:
{
fseek( file, 84, SEEK_CUR );
}
case 7:
{
fseek( file, 8, SEEK_CUR );
}
case 8:
{
static length;
fseek( file, 4, SEEK_CUR );
fread( file, length, BLOCK_INT );
fseek( file, length, SEEK_CUR );
fseek( file, 16, SEEK_CUR );
}
case 9:
{
static length;
fread( file, length, BLOCK_INT );
fseek( file, length, SEEK_CUR );
}
default:
{
breakme = true;
}
}
if(type == 1)
{
temp_data[frame_time] = _:gametime;
ArrayPushArray(array_to, temp_data);
}
if(breakme)
{
return true;
}
}
return false;
}
/************************************************
* *
* FILE OPERATING SECTION *
* *
*************************************************/
public load_run(filename[128])
{
new file = fopen(filename, "r");
new string[300];
new player_name[32], demo_time[32], demo_type[32];
fgets(file, string, charsmax(string));
if(containi(string, "HEADER") == -1)
{
fclose(file)
return -1;
}
static ExplodedString[14][32];
ExplodeString( ExplodedString, 4, 127, string, ' ' );
copy(player_name, 32, ExplodedString[1])
copy(demo_type, 32, ExplodedString[2])
copy(demo_time, 32, ExplodedString[3])
static temp_frame[frame_data];
new id = sources_num;
bot_sources[id][source_type] = 0;
bot_sources[id][source_id] = sources_num;
bot_sources[id][source_name] = player_name;
bot_sources[id][source_time] = demo_time;
bot_sources[id][source_path] = filename;
remove_quotes(bot_sources[id][source_name])
remove_quotes(bot_sources[id][source_time])
remove_quotes(demo_type)
trim(bot_sources[id][source_name])
trim(bot_sources[id][source_time])
trim(demo_type)
if(equal(demo_type, "DEMO"))
{
bot_sources[id][source_type] = 1;
}
sources_num++
ArrayClear(bot_sources[id][source_array]);
while(fgets(file, string, charsmax(string)))
{
ExplodeString( ExplodedString, 13, 31, string, ' ' );
temp_frame[frame_origin][0] = _:str_to_float(ExplodedString[1])
temp_frame[frame_origin][1] = _:str_to_float(ExplodedString[2])
temp_frame[frame_origin][2] = _:str_to_float(ExplodedString[3])
temp_frame[frame_angles][0] = _:str_to_float(ExplodedString[4])
temp_frame[frame_angles][1] = _:str_to_float(ExplodedString[5])
temp_frame[frame_angles][2] = _:str_to_float(ExplodedString[6])
temp_frame[frame_velocity][0] = _:str_to_float(ExplodedString[7])
temp_frame[frame_velocity][1] = _:str_to_float(ExplodedString[8])
temp_frame[frame_velocity][2] = _:str_to_float(ExplodedString[9])
temp_frame[frame_buttons] = _:str_to_num(ExplodedString[10])
temp_frame[frame_time] = _:str_to_float(ExplodedString[11])
ArrayPushArray(bot_sources[id][source_array], temp_frame)
}
fclose(file)
return id;
}
public save_run(id, demo_time[32], bool:is_demofile)
{
new sz_name[32], sz_steam[32], filename[128]
if(!is_demofile)
{
get_user_name(id, sz_name, 63);
get_user_authid(id, sz_steam, 63);
}
else
{
copy(sz_name, 32, bot_sources[id][source_name]);
copy(demo_time, 32, bot_sources[id][source_time])
sz_steam = "DEMO"
}
replace_all(sz_name, charsmax(sz_name), "^"", "");
replace_all(sz_name, charsmax(sz_name), "^'", "");
format(filename, charsmax(filename), "%s/[%s] %s.rec", map_records_dir, demo_time, sz_name);
new file = fopen(filename, "wb");
new string[300];
format(string, charsmax(string), "HEADER ^"%s^" ^"%s^" ^"%s^" ^n", sz_name, sz_steam, demo_time);
fputs(file, string);
new Array:array;
if(is_demofile)
{
array = bot_sources[id][source_array]
}
else
{
array = record_info[id]
}
new arrsize = ArraySize(array);
new temp_frame[frame_data];
for(new i = 0; i < arrsize; i++ )
{
ArrayGetArray( array, i, temp_frame );
format(string, charsmax(string), "INFO %f %f %f %f %f %f %f %f %f %d %f^n", temp_frame[frame_origin][0],
temp_frame[frame_origin][1], temp_frame[frame_origin][2], temp_frame[frame_angles][0], temp_frame[frame_angles][1],
temp_frame[frame_angles][2], temp_frame[frame_velocity][0], temp_frame[frame_velocity][1], temp_frame[frame_velocity][2],
temp_frame[frame_buttons], temp_frame[frame_time]);
fputs(file, string);
}
fclose(file);
if(!is_demofile)
{
new bool:replacesource = false;
new replaceid;
if(sources_num)
{
for(new i = 0; i < sources_num; i++)
{
if(!bot_sources[id][source_type])
{
replacesource = true;
replaceid = i;
break;
}
}
}
if(replacesource)
{
arrayset(plr_botnamed, false, 32);
new recordbackup[128];
format(recordbackup, charsmax(recordbackup), "%s.bak", bot_sources[replaceid][source_path]);
fcopy(bot_sources[replaceid][source_path],recordbackup, FW_CANOVERRIDE | FW_DELETESOURCE);
}
new id = sources_num;
if(replacesource)
id = replaceid;
bot_sources[id][source_id] = id;
bot_sources[id][source_name] = sz_name;
bot_sources[id][source_time] = demo_time;
bot_sources[id][source_path] = filename;
bot_sources[id][source_startframe] = 0;
ArrayGetArray( array, 1, temp_frame );
bot_sources[id][source_starttime] = _:temp_frame[frame_time];
bot_sources[id][source_stoptime] = _:0.0;
bot_sources[id][source_type] = 0;
CloneRun(array, bot_sources[id][source_array], true);
if(!replacesource)
sources_num++
//kzbot_create_bot(id);
}
}
public already_parsed(player_name[], wr_time[])
{
for(new i = 0; i < MAX_SOURCES; i++)
{
remove_quotes(bot_sources[i][source_name])
remove_quotes(bot_sources[i][source_time])
trim(bot_sources[i][source_name])
trim(bot_sources[i][source_time])
if(equal(bot_sources[i][source_time],wr_time) && equal(bot_sources[i][source_name], player_name))
{
return true;
}
}
return false;
}
public OnDemosComplete(is_cosy)
{
new iArchiveName[256];
new datadir[128], record_list[128];
get_localinfo( "amxx_datadir", datadir, charsmax( datadir ) );
format(datadir, charsmax(datadir), "%s/%s", datadir, rec_foldername);
if(!is_cosy)
{
format(record_list, charsmax(record_list), "%s/record_list.txt", datadir);
server_print( "Parsing XJ Demo List" );
}
else
{
format(record_list, charsmax(record_list), "%s/record_list2.txt", datadir);
server_print( "Parsing CC Demo List" );
}
new ExplodedString[7][128];
new Line[128];
new MapName[2][64];
get_mapname( MapName[0], 63 );
format(MapName[1], charsmax(MapName[]), "%s[", MapName[0]);
format(MapName[0], charsmax(MapName[]), "%s ", MapName[0]);
new lines = file_size(record_list, 1);
for(new i = 1; i < lines; i++)
{
new len;
read_file(record_list, i, Line, charsmax( Line ), len);
//fgets( iDemosList, Line, charsmax( Line ) );
ExplodeString( ExplodedString, 6, 127, Line, ' ' );
new parsedmap[128];
parsedmap = ExplodedString[0];
format( parsedmap, charsmax( parsedmap ), "%s ", parsedmap );
if ( containi( parsedmap, MapName[0] ) > -1 || containi( parsedmap, MapName[1] ) > -1 )
{
new sWRTime[24];
new Float:Date = str_to_float( ExplodedString[1] );
fnConvertTime( Date, sWRTime, charsmax( sWRTime ) );
if(is_cosy)
strtolower(ExplodedString[0]);
format( iArchiveName, charsmax( iArchiveName ), "%s_%s_%s", ExplodedString[0], ExplodedString[2], sWRTime );
new iLink[512];
if(!is_cosy)
format( iLink, charsmax( iLink ), "http://files.xtreme-jumps.eu/demos/%s.rar", iArchiveName );
else
format( iLink, charsmax( iLink ), "https://cosy-climbing.net/files/demos/%s.rar", iArchiveName );
new datadir[128];
get_localinfo( "amxx_datadir", datadir, charsmax( datadir ) );
format( datadir, charsmax( datadir ), "%s/%s.rar", datadir, iArchiveName );
if(!already_parsed(ExplodedString[2], sWRTime))
curl_download_file(datadir, iLink, ExplodedString[2], sWRTime );
}
}
return -1;
}
public process_list( filename[] )
{
if(contain(filename, "record_list2") != -1)
{
OnDemosComplete(1);
}
else
OnDemosComplete(0);
}
public process_demo(id)
{
new filename[128]
read_args(filename, charsmax(filename))
new file = fopen(filename, "rb");
if(is_valid_demo_file(file))
{
if(read_demo_header( file ))
{
new Ent = engfunc( EngFunc_CreateNamedEntity , engfunc( EngFunc_AllocString,"info_target" ) );
set_pev(Ent, pev_classname, rec_demoparser);
set_pev(Ent, pev_iuser1, file );
set_pev(Ent, pev_iuser2, sources_num );
set_pev(Ent, pev_iuser3, EncodeText(filename) );
formatex(bot_sources[sources_num][source_name], 32, "test");
formatex(bot_sources[sources_num][source_time], 32, "test");
set_pev(Ent, pev_nextthink, get_gametime() + 0.01 );
sources_num++
}
}
}
public process_archive( filename[128], player_name[], wr_time[])
{
//new length = strlen(filename);
new destname[128]
//delete_file(filename);
get_localinfo( "amxx_datadir", destname, charsmax( destname ) );
format(destname, charsmax(destname), "%s/demo%d.dem", destname, sources_num);
AA_Unarchive(filename, destname);
//replace(filename, length, ".rar", ".dem");
new file = fopen(destname, "rb");
if(is_valid_demo_file(file))
{
if(read_demo_header( file ))
{
new Ent = engfunc( EngFunc_CreateNamedEntity , engfunc( EngFunc_AllocString,"info_target" ) );
set_pev(Ent, pev_classname, rec_demoparser);
set_pev(Ent, pev_iuser1, file );
set_pev(Ent, pev_iuser2, sources_num );
set_pev(Ent, pev_iuser3, EncodeText(filename) );
formatex(bot_sources[sources_num][source_name], 32, "%s", player_name, wr_time);
formatex(bot_sources[sources_num][source_time], 32, "%s", wr_time);
set_pev(Ent, pev_nextthink, get_gametime() + 3.0 );
sources_num++
}
}
}
public bool:is_valid_demo_file( file )
{
fseek( file, 0, SEEK_END );
new header_size = ftell( file );
if ( header_size < 544 )
{
return(false);
}
fseek( file, 0, SEEK_SET );
new signature[6];
fread_blocks( file, signature, sizeof(signature), BLOCK_CHAR );
if ( !contain( "HLDEMO", signature ) )
{
return(false);
}
return(true);
}
/************************************************
* *
* INTERNET STREAM SECTION (CURL) *
* *
*************************************************/
#define CURL_BUFFER_SIZE 256
public curl_download_file( file[], link[], player_name[], wr_time[] )
{
new data[4]
data[0] = fopen(file, "wb")
data[1] = EncodeText( file );
data[2] = EncodeText( player_name );
data[3] = EncodeText( wr_time );
new CURL:curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, link);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, data[0]);
/* ATTENTION ATTENTION ATTENTION
Without CURLOPT_NOSIGNAL on Linux Machines CURL can cause SEG FAULT even on idle state (idk why), better not remove this line
ATTENTION ATTENTION ATTENTION*/
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, "write");
curl_easy_perform(curl, "complite", data, sizeof(data));
}
public write(data[], size, nmemb, file)
{
new actual_size = size * nmemb;
fwrite_blocks(file, data, actual_size, BLOCK_CHAR)
return actual_size
}
public complite(CURL:curl, CURLcode:code, data[])
{
static file[128];
static player_name[32];
static wr_time[16];
fclose(data[0])
curl_easy_cleanup(curl)
DecodeText(data[1], file, charsmax(file))
DecodeText(data[2], player_name, charsmax(player_name))
DecodeText(data[3], wr_time, charsmax(wr_time))
if(containi(file, ".txt") != -1)
{
process_list(file);
}
else
{
process_archive(file, player_name, wr_time);
}
}
/************************************************
* *
* BOT MANAGE SECTION *
* *
*************************************************/
public kzbot_settings(id)
{
new menu = menu_create( "\rBot Playback:", "kzbot_settings_handle" );
new text[256];
menu_additem( menu, "\wStart/Restart Bot", "1");
menu_additem( menu, "\wPause/Unpause Bot", "2");
menu_additem( menu, "\wStop Bot", "3");
if(global_bot)
menu_additem( menu, "\wKick Bot", "4", ADMIN_KICK);
else
menu_additem( menu, "\wAdd Bot", "4", ADMIN_KICK);
menu_additem( menu, "\wFast forward", "5");
menu_additem( menu, "\wFast backward", "6");
format(text, charsmax(text), "\wFast Interval: %0.f sec ", float(plr_jump[id])/100.0);
menu_additem(menu, text, "7");
format(text, charsmax(text), "\wBot mode: %s", bot_modes[plr_mode[id]]);
menu_additem(menu, text, "8");
new sz_name[32]
format(sz_name, charsmax(sz_name), "[%s] %s %.2s:%.2s.%.2s", bot_sources[plr_source[id]][source_type] == 1 ? "WR" : "REC", bot_sources[plr_source[id]][source_name], bot_sources[plr_source[id]][source_time], bot_sources[plr_source[id]][source_time][2], bot_sources[plr_source[id]][source_time][5]);
format(text, charsmax(text), "\wBot Source: %s", sz_name);
menu_additem( menu, text, "9");
menu_additem( menu, "Exit", "0" )
menu_setprop(menu, MPROP_PERPAGE, 0);
menu_setprop( menu, MPROP_EXIT, MEXIT_ALL );
menu_display( id, menu, 0 );
return PLUGIN_HANDLED;
}
public kzbot_settings_handle(id, menu, item)
{
if( item == MENU_EXIT )
{
menu_destroy( menu );
return PLUGIN_HANDLED;
}
switch( item )
{
case 0:
{
plr_frame_it[id] = 0;
plr_playback[id] = true;
}
case 1:
{
plr_playback[id] = !plr_playback[id]
}
case 2:
{
plr_frame_it[id] = 0;
plr_playback[id] = false;
}
case 3:
{
if((get_user_flags(id) & ADMIN_KICK))
{
if(global_bot)
{
server_cmd("kick #%d",get_user_userid(global_bot))
global_bot = 0;
}
else
{
global_bot = makebot("Record bot");
arrayset(plr_botnamed, false, 32);
}
}
}
case 4:
{
plr_frame_it[id] += plr_jump[id];
if(plr_frame_it[id] > ArraySize(bot_sources[plr_source[id]][source_array])-1)
{
plr_frame_it[id] = 0;
}
}
case 5:
{
plr_frame_it[id] -= plr_jump[id];
if(plr_frame_it[id] < 0)
{
plr_frame_it[id] = 0;
}
}
case 6:
{
plr_jump[id] += 300;
if(plr_jump[id] > 3000)
{
plr_jump[id] = 300;
}
}
case 7:
{
if(++plr_mode[id] > sizeof(bot_modes)-1)
plr_mode[id] = 0;
}
case 8:
{
if(++plr_source[id] == sources_num)
plr_source[id] = 0;
update_sourcename(id)
}
case 9:
{
menu_destroy( menu );
return PLUGIN_HANDLED;
}
}
kzbot_settings(id)
return PLUGIN_HANDLED;
}
public kzbot_menu(id)
{
kzbot_settings(id);
}
public makebot(name[64])
{
remove_quotes(name);
trim(name)
new bot = engfunc( EngFunc_CreateFakeClient, name );
if ( !bot )
{
server_print( "Couldn't create a bot, server full?" );
return 0;
}
engfunc( EngFunc_FreeEntPrivateData, bot );
bot_settings( bot );
static szRejectReason[128];
dllfunc( DLLFunc_ClientConnect, bot, name, "127.0.0.1", szRejectReason );
if ( !is_user_connected( bot ) )
{
server_print( "Connection rejected: %s", szRejectReason );
return 0;
}
dllfunc( DLLFunc_ClientPutInServer, bot );
set_pev( bot, pev_spawnflags, pev( bot, pev_spawnflags ) | FL_FAKECLIENT );
set_pev( bot, pev_flags, pev( bot, pev_flags ) | FL_FAKECLIENT );
engclient_cmd( bot , "jointeam" , "2" )
engclient_cmd( bot , "joinclass" , "1" )
fm_cs_set_user_team(bot, 2);
ExecuteHamB( Ham_CS_RoundRespawn, bot );
fm_set_user_godmode( bot, 1 );
return bot;
}
public bot_settings( id )
{
set_user_info( id, "model", "gordon" );
set_user_info( id, "rate", "3500" );
set_user_info( id, "cl_updaterate", "30" );
set_user_info( id, "cl_lw", "0" );
set_user_info( id, "cl_lc", "0" );
set_user_info( id, "tracker", "0" );
set_user_info( id, "cl_dlmax", "128" );
set_user_info( id, "lefthand", "1" );
set_user_info( id, "friends", "0" );
set_user_info( id, "dm", "0" );
set_user_info( id, "ah", "1" );
set_user_info( id, "*bot", "1" );
set_user_info( id, "_cl_autowepswitch", "0" );
set_user_info( id, "_vgui_menu", "0" ); /* disable vgui so we dont have to */
set_user_info( id, "_vgui_menus", "0" ); /* register both 2 types of menus :) */
}
/************************************************
* *
* NATIVES SECTION *
* *
*************************************************/
public delayed_save(id, data[32])
{
plr_saverun_time[id] = data;
plr_delayed_save[id] = true;
plr_delayed_timer[id] = get_gametime() + 1.0;
}
public native_save_run(plugin_id, params)
{
static id; id = get_param(1);
new demo_time[32];
get_string(2,demo_time,31);
delayed_save(id, demo_time);
}
public native_reset_run(plugin_id, params)
{
static id; id = get_param(1);
if(plr_delayed_save[id])
{
save_run(id, plr_saverun_time[id], false);
plr_delayed_save[id] = false;
}
if(global_bot != id)
ArrayClear(record_info[id]);
}
public native_pause_run(plugin_id, params)
{
static id; id = get_param(1);
is_recording[id] = false;
}
public native_unpause_run(plugin_id, params)
{
static id; id = get_param(1);
is_recording[id] = true;
}
/************************************************
* *
* STOCK UTILITIES SECTION *
* *
*************************************************/
#define BUFFERSIZE 256
stock fcopy(read_path[], dest_path[], FWrite:flags = FW_NONE)
{
// Prepare for read
new fp_read = fopen(read_path, "rb")
// No file to read, errors!
if (!fp_read)
{
fclose(fp_read)
return 0
}
// If the native cannot override
if (file_exists(dest_path) && !(flags & FW_CANOVERRIDE))
{
return 0
}
// Prepare for write
new fp_write = fopen(dest_path, "wb")
// Used for copying
static buffer[BUFFERSIZE]
static readsize
// Find the size of the files
fseek(fp_read, 0, SEEK_END);
new fsize = ftell(fp_read);
fseek(fp_read, 0, SEEK_SET);
// Here we copy the info
for (new j = 0; j < fsize; j += BUFFERSIZE)
{
readsize = fread_blocks(fp_read, buffer, BUFFERSIZE, BLOCK_CHAR);
fwrite_blocks(fp_write, buffer, readsize, BLOCK_CHAR);
}
// Close the files
fclose(fp_read)
fclose(fp_write)
// Can delete source?
if (flags & FW_DELETESOURCE)
delete_file(read_path)
// Success
return 1
}
stock ExplodeString( p_szOutput[][], p_nMax, p_nSize, p_szInput[], p_szDelimiter )
{
new nIdx = 0, l = strlen( p_szInput );
new nLen = (1 + copyc( p_szOutput[nIdx], p_nSize, p_szInput, p_szDelimiter ) );
while ( (nLen < l) && (++nIdx < p_nMax) )
nLen += (1 + copyc( p_szOutput[nIdx], p_nSize, p_szInput[nLen], p_szDelimiter ) );
return(nIdx);
}
stock fnConvertTime( Float:time, convert_time[], len )
{
new sTemp[24];
new Float:fSeconds = time, iMinutes;
iMinutes = floatround( fSeconds / 60.0, floatround_floor );
fSeconds -= iMinutes * 60.0;
new intpart = floatround( fSeconds, floatround_floor );
new Float:decpart = (fSeconds - intpart) * 100.0;
intpart = floatround( decpart );
formatex( sTemp, charsmax( sTemp ), "%02i%02.0f.%02d", iMinutes, fSeconds, intpart );
formatex( convert_time, len, sTemp );
return(PLUGIN_HANDLED);
}
#define PEV_PDATA_SAFE 2
#define OFFSET_TEAM 114
#define OFFSET_DEFUSE_PLANT 193
#define HAS_DEFUSE_KIT (1<<16)
#define OFFSET_INTERNALMODEL 126
stock fm_cs_set_user_team(id, team)
{
if(!(1 <= id <= maxplayers) || pev_valid(id) != PEV_PDATA_SAFE)
{
return 0
}
switch(team)
{
case 1:
{
new iDefuser = get_pdata_int(id, OFFSET_DEFUSE_PLANT)
if(iDefuser & HAS_DEFUSE_KIT)
{
iDefuser -= HAS_DEFUSE_KIT
set_pdata_int(id, OFFSET_DEFUSE_PLANT, iDefuser)
}
set_pdata_int(id, OFFSET_TEAM, 1)
// set_pdata_int(id, OFFSET_INTERNALMODEL, 4)
}
case 2:
{
if(pev(id, pev_weapons) & (1<<CSW_C4))
{
engclient_cmd(id, "drop", "weapon_c4")
}
set_pdata_int(id, OFFSET_TEAM, 2)
// set_pdata_int(id, OFFSET_INTERNALMODEL, 6)
}
}
dllfunc(DLLFunc_ClientUserInfoChanged, id, engfunc(EngFunc_GetInfoKeyBuffer, id))
return 1
}
stock EncodeText( const text[] )
{
return engfunc( EngFunc_AllocString, text )
}
stock DecodeText( const text, string[], const length )
{
global_get( glb_pStringBase, text, string, length )
}
stock animate_legs(es_handle, keys, bool:onground)
{
#define InMove (keys & IN_FORWARD || keys & IN_LEFT || keys & IN_RIGHT || keys & IN_BACK)
//client_print(0, print_chat, "%d", onground);
if (onground)
{
if ( keys & IN_DUCK && InMove )
{
set_es(es_handle, ES_GaitSequence, 5 );
}else if ( keys & IN_DUCK )
{
set_es(es_handle, ES_GaitSequence, 2 );
}else {
set_es(es_handle, ES_GaitSequence, 4 );
}
if ( keys & IN_JUMP )
{
set_es(es_handle, ES_GaitSequence, 6 );
}else {
set_es(es_handle, ES_GaitSequence, 4 );
}
}else {
set_es(es_handle, ES_GaitSequence, 6 );
if ( keys & IN_DUCK )
{
set_es(es_handle, ES_GaitSequence, 5 );
}
}
}
stock CloneRun( Array:source_arr, Array:dest_arr, bool:clean )
{
static len; len = ArraySize(source_arr);
static data[frame_data];
if(clean)
ArrayClear(dest_arr);
for(new i = 0; i < len; i++)
{
ArrayGetArray(source_arr, i, data);
ArrayPushArray(dest_arr, data);
}
}
stock kick_user(id)
{
new userid2 = get_user_userid(id)
if (is_user_bot(id))
server_cmd("kick #%d", userid2)
}
public playback_sound(id, Float:origin[3])
{
static stepleft[33];
if(plr_sound[id] > 0)
{
return 0;
}
stepleft[id] = !stepleft[id]
new irand = random_num(0,1) + (stepleft[id] * 2)
plr_sound[id] = 300;
spawnStaticSound(id, origin, step_sounds[irand], 1.0, ATTN_NORM, PITCH_NORM, 0);
return 0;
}
#define clamp_byte(%1) ( clamp( %1, 0, 255 ) )
#define write_coord_f(%1) ( engfunc( EngFunc_WriteCoord, %1 ) )
stock spawnStaticSound( const index, const Float:origin[3], const soundIndex, const Float:vol, const Float:atten, const pitch, const flags )
{
message_begin( index ? MSG_ONE : MSG_ALL, SVC_SPAWNSTATICSOUND, .player = index );
{
write_coord_f( origin[0] );
write_coord_f( origin[1] );
write_coord_f( origin[2] );
write_short( soundIndex );
write_byte( clamp_byte( floatround( vol * 255 ) ) );
write_byte( clamp_byte( floatround( atten * 64 ) ) );
write_short( 0 );
write_byte( pitch );
write_byte( flags );
}
message_end();
}
stock set_user_fake_name(const id, const name[])
{
message_begin(MSG_ONE, SVC_UPDATEUSERINFO, _, id)
write_byte(global_bot - 1)
write_long(get_user_userid(global_bot))
write_char('\')
write_char('n')
write_char('a')
write_char('m')
write_char('e')
write_char('\')
write_string(name)
for(new i; i < 16; i++) write_byte(0)
message_end()
}
public update_sourcename( id )
{
new sz_name[32]
format(sz_name, charsmax(sz_name), "[%s] %s %.2s:%.2s.%.2s", bot_sources[plr_source[id]][source_type] == 1 ? "WR" : "REC", bot_sources[plr_source[id]][source_name], bot_sources[plr_source[id]][source_time], bot_sources[plr_source[id]][source_time][2], bot_sources[plr_source[id]][source_time][5]);
set_user_fake_name(id, sz_name);
}