#include #include #include #include #include #include #include #include #include #define PLUGIN "KZ_Bot" #define VERSION "1.23" #define AUTHOR "Flummi & MichaelKheel" //#define DEV_DEBUG new g_szMapName[32]; new Array:fPlayerAngle, Array:fPlayerKeys, Array:fPlayerVelo, Array:fPlayerOrigin; new g_timer; // Timer new Float:timer_time[33], bool:timer_started[33], bool:IsPaused[33], Float:g_pausetime[33], bool:bot_finish_use[33]; new g_bot_start, g_bot_enable, g_bot_frame, wr_bot_id; new SyncHudBotTimer; new Trie:g_tButtons[2]; new url_sprite[64], url_sprite_xz[64]; new WR_TIME[130], WR_NAME[130], WR_COUNTRY[130], WR_SRC[5]; new Float:nExttHink = 0.009; new timer_bot, timer_option; new Float:flStartTime; #define NUM_THREADS 256 #pragma dynamic 32767 #define PEV_PDATA_SAFE 2 #define OFFSET_TEAM 114 #define OFFSET_DEFUSE_PLANT 193 #define HAS_DEFUSE_KIT (1<<16) #define OFFSET_INTERNALMODEL 126 new bool:g_Demos = false; new iXJWRs, iCCWRs, iKZRUWRs, iArchive; new bool:bFoundDemo = false; new iDemo_header_size; new iArchiveName[256]; new iDemoName[256]; new iNavName[256]; new iFile; new iParsedFile; new g_demoExt[32] = "rar"; public plugin_precache() { get_mapname(g_szMapName, sizeof(g_szMapName) - 1); strtolower(g_szMapName); parsing_country("xj"); new i; for(i = 0; i < sizeof(g_tButtons); i++) g_tButtons[i] = TrieCreate(); new szStartTargets[][] = { "counter_start", "clockstartbutton", "firsttimerelay", "but_start", "counter_start_button", "multi_start", "timer_startbutton", "start_timer_emi", "gogogo" }; for(i = 0; i < sizeof szStartTargets ; i++) TrieSetCell(g_tButtons[0], szStartTargets[i], i); new szFinishTargets[][] = { "counter_off", "clockstopbutton", "clockstop", "but_stop", "counter_stop_button", "multi_stop", "stop_counter", "m_counter_end_emi" }; for(i = 0; i < sizeof szFinishTargets; i++) TrieSetCell(g_tButtons[1], szFinishTargets[i], i); new Ent = engfunc(EngFunc_CreateNamedEntity , engfunc(EngFunc_AllocString, "info_target")); set_pev(Ent, pev_classname, "BotThink"); set_pev(Ent, pev_nextthink, get_gametime() + 0.01); register_forward(FM_Think, "fwd_Think", 1); fPlayerAngle = ArrayCreate(2); fPlayerOrigin = ArrayCreate(3); fPlayerVelo = ArrayCreate(3); fPlayerKeys = ArrayCreate(1); } public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR); timer_bot = register_cvar("timer_bot", "1"); timer_option = register_cvar("timer_option", "1"); // 1 txt, 2 hud new kreedz_cfg[128], ConfigDir[64]; get_configsdir(ConfigDir, 64); formatex(kreedz_cfg, 128, "%s/wrbot.cfg", ConfigDir); if(file_exists(kreedz_cfg)) { server_cmd("exec %s", kreedz_cfg); server_exec(); } else server_print("[WR_BOT] Config file is not connected, please check."); if(get_pcvar_num(timer_bot) == 1) { new iTimerEnt = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString , "info_target")); set_pev(iTimerEnt, pev_classname, "kz_time_think"); set_pev(iTimerEnt, pev_nextthink, get_gametime() + 1.0); } SyncHudBotTimer = CreateHudSyncObj(); announce(); } public Ham_ButtonUse(id) { new Float:origin[3]; pev(id, pev_origin, origin); new ent = -1; while((ent = find_ent_in_sphere(ent, origin, 100.0)) != 0) { new classname[32]; pev(ent, pev_classname, classname, charsmax(classname)); new Float:eorigin[3]; get_brush_entity_origin(ent, eorigin); static Float:Distance[2]; new szTarget[32]; pev(ent, pev_target, szTarget, 31); if(TrieKeyExists(g_tButtons[0], szTarget)) { if(g_bot_start < 0) g_bot_start = 0; if(vector_distance(origin, eorigin) >= Distance[0]) { timer_time[id] = get_gametime(); IsPaused[id] = false; timer_started[id] = true; bot_finish_use[id] = false; } Distance[0] = vector_distance(origin, eorigin); } if(TrieKeyExists(g_tButtons[1], szTarget)) { if(vector_distance(origin, eorigin) >= Distance[1]) { if(!bot_finish_use[id]) { if(timer_started[id]) Start_Bot(); timer_started[id] = false; bot_finish_use[id] = true; } } Distance[1] = vector_distance(origin, eorigin); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TIMER ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public timer_task(iTimer) { new Dead[32], deadPlayers; get_players(Dead, deadPlayers, "bh"); for(new i = 0; i < deadPlayers; i++) { new specmode = pev(Dead[i], pev_iuser1); if(specmode == 2 || specmode == 4) { new target = pev(Dead[i], pev_iuser2); if(is_user_alive(target)) { if(timer_started[target] && target == wr_bot_id) { new Float:kreedztime = get_gametime() - (IsPaused[target] ? get_gametime() - g_pausetime[target] : timer_time[target]); new imin = floatround(kreedztime / 60.0, floatround_floor); new isec = floatround(kreedztime - imin * 60, floatround_floor); new mili = floatround((kreedztime - (imin * 60 + isec)) * 100, floatround_floor); if(get_pcvar_num(timer_option) == 1) { client_print(Dead[i], print_center, "[ %02i:%02i.%02i | HP: Godmode | 10aa ]", imin, isec, mili, IsPaused[target] ? "| *Paused*" : ""); } else if(get_pcvar_num(timer_option) == 2) { set_hudmessage(255, 255, 255, -1.0, 0.35, 0, 0.0, 1.0, 0.0, 0.0); ShowSyncHudMsg(Dead[i], SyncHudBotTimer, "[ %02i:%02i.%02i | HP: Godmode | 10aa ]", imin, isec, mili, IsPaused[target] ? "| *Paused*" : ""); } } else if(!timer_started[target] && target == wr_bot_id) { client_print(Dead[i], print_center, ""); } } } } entity_set_float(iTimer, EV_FL_nextthink, get_gametime() + 0.07) } public Pause() { if(!IsPaused[wr_bot_id]) { g_pausetime[wr_bot_id] = get_gametime() - timer_time[wr_bot_id]; timer_time[wr_bot_id] = 0.0; IsPaused[wr_bot_id] = true; g_bot_enable = 2; } else { if(timer_started[wr_bot_id]) { timer_time[wr_bot_id] = get_gametime() - g_pausetime[wr_bot_id]; } IsPaused[wr_bot_id] = false; g_bot_enable = 1; } } public fwd_Think(iEnt) { if(!pev_valid(iEnt)) return(FMRES_IGNORED); static className[32]; pev(iEnt, pev_classname, className, 31); if(equal(className, "DemThink")) { static bool:Finished; for(new i = 0; i < NUM_THREADS; i++) { if(ReadFrames(iFile)) { Finished = true; break; } } if(Finished) { set_pev(iEnt, pev_flags, pev(iEnt, pev_flags) | FL_KILLME); fclose(iFile); // rename file iDemoName -> path/iArchiveName.dem new sDatadir[128], sNewfile[128]; get_localinfo("amxx_datadir", sDatadir, charsmax(sDatadir)); format(sNewfile, charsmax(sNewfile), "%s/demos/%s/%s.dem", sDatadir, g_szMapName, iArchiveName); if(!rename_file(iDemoName, sNewfile, 1)) // relative delete_file(iDemoName); server_print("from: %s", iDemoName); server_print(" to: %s", sNewfile); LoadParsedInfo(iNavName); } else set_pev(iEnt, pev_nextthink, get_gametime() + 0.001); } if(equal(className, "NavThink")) { static bool:Finished; for(new i = 0; i < NUM_THREADS; i++) { if(!ReadParsed(iEnt)) { Finished = true; break; } } if(Finished) { set_pev(iEnt, pev_flags, pev(iEnt, pev_flags) | FL_KILLME); delete_file(iNavName); set_task(2.0, "StartCountDown"); } } if(equal(className, "kz_time_think")) { timer_task(1); set_pev(iEnt, pev_nextthink, get_gametime() + 0.08); } if(equal(className, "BotThink")) { BotThink(wr_bot_id); set_pev(iEnt, pev_nextthink, get_gametime() + nExttHink); } return(FMRES_IGNORED); } public BotThink(id) { static Float:ViewOrigin[3], Float:ViewAngle[3], Float:ViewVelocity[3], ViewKeys; static Float:last_check, Float:game_time, nFrame; game_time = get_gametime(); if(game_time - last_check > 1.0) { if(nFrame < 100) nExttHink = nExttHink - 0.0001; else if(nFrame > 100) nExttHink = nExttHink + 0.0001; nFrame = 0; last_check = game_time; } if(g_bot_enable == 1 && wr_bot_id) { g_bot_frame++; if(g_bot_frame < ArraySize(fPlayerAngle)) { ArrayGetArray(fPlayerOrigin, g_bot_frame, ViewOrigin); ArrayGetArray(fPlayerAngle, g_bot_frame, ViewAngle); ArrayGetArray(fPlayerVelo, g_bot_frame, ViewVelocity); ViewKeys = ArrayGetCell(fPlayerKeys, g_bot_frame); if(ViewKeys&IN_ALT1) ViewKeys|=IN_JUMP; if(ViewKeys&IN_RUN) ViewKeys|=IN_DUCK; if(ViewKeys&IN_RIGHT) { engclient_cmd(id, "weapon_usp"); ViewKeys&=~IN_RIGHT; } if(ViewKeys&IN_LEFT) { engclient_cmd(id, "weapon_knife"); ViewKeys&=~IN_LEFT; } if(ViewKeys & IN_USE) { Ham_ButtonUse(id); ViewKeys &= ~IN_USE; } engfunc(EngFunc_RunPlayerMove, id, ViewAngle, ViewVelocity[0], ViewVelocity[1], 0.0, ViewKeys, 0, 10); set_pev(id, pev_v_angle, ViewAngle); ViewAngle[0] /= -3.0; set_pev(id, pev_velocity, ViewVelocity); set_pev(id, pev_angles, ViewAngle); set_pev(id, pev_origin, ViewOrigin); set_pev(id, pev_button, ViewKeys ); if(pev(id, pev_gaitsequence) == 4 && ~pev(id, pev_flags) & FL_ONGROUND) set_pev(id, pev_gaitsequence, 6); if(nFrame == ArraySize(fPlayerAngle) - 1) Start_Bot(); } else g_bot_frame = 0; } nFrame++; } Create_Bot() { new txt[64] formatex(txt, charsmax(txt), "[%s] %s %s (%s)", WR_SRC, WR_NAME, WR_TIME, WR_COUNTRY); new id = engfunc(EngFunc_CreateFakeClient, txt); if(pev_valid(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_cmdrate", "60"); set_user_info(id, "cl_lw", "0"); set_user_info(id, "cl_lc", "0"); set_user_info(id, "cl_dlmax", "128"); set_user_info(id, "cl_righthand", "0"); set_user_info(id, "ah", "1"); set_user_info(id, "dm", "0"); set_user_info(id, "tracker", "0"); set_user_info(id, "friends", "0"); set_user_info(id, "*bot", "1"); set_user_info(id, "_cl_autowepswitch", "1"); set_user_info(id, "_vgui_menu", "0"); set_user_info(id, "_vgui_menus", "0"); static szRejectReason[128]; dllfunc(DLLFunc_ClientConnect, id, "WR BOT", "127.0.0.1" , szRejectReason); if(!is_user_connected(id)) { server_print("Connection rejected: %s", szRejectReason); return 0; } dllfunc(DLLFunc_ClientPutInServer, id); set_pev(id, pev_spawnflags, pev(id, pev_spawnflags) | FL_FAKECLIENT); set_pev(id, pev_flags, pev(id, pev_flags) | FL_FAKECLIENT); cs_set_user_team(id, CS_TEAM_CT); cs_set_user_model(id, "sas"); cs_set_user_bpammo(id, CSW_USP, 250); cs_user_spawn(id); give_item(id, "weapon_knife"); give_item(id, "weapon_usp"); set_user_godmode(id, 1); return id; } return 0; } public StartCountDown() { if(!wr_bot_id) wr_bot_id = Create_Bot(); g_timer = 0; set_task(1.0, "Show"); } public Show() { g_timer--; set_hudmessage(255, 255, 255, 0.05, 0.2, 0, 6.0, 1.0); if(g_timer && g_timer >= 0) set_task(1.0, "Show"); else { g_bot_enable = 1; Start_Bot(); } } Start_Bot() { g_bot_frame = g_bot_start; timer_started[wr_bot_id] = false; } public client_disconnected(id) { if(id == wr_bot_id) { timer_time[id] = 0.0; IsPaused[wr_bot_id] = false; timer_started[wr_bot_id] = false; g_bot_enable = 0; g_bot_frame = 0; wr_bot_id = 0; } } enum _:Consts { HEADER_SIZE = 544, HEADER_SIGNATURE_CHECK_SIZE = 6, HEADER_SIGNATURE_SIZE = 8, HEADER_MAPNAME_SIZE = 260, HEADER_GAMEDIR_SIZE = 260, MIN_DIR_ENTRY_COUNT = 1, MAX_DIR_ENTRY_COUNT = 1024, DIR_ENTRY_SIZE = 92, DIR_ENTRY_DESCRIPTION_SIZE = 64, MIN_FRAME_SIZE = 12, FRAME_CONSOLE_COMMAND_SIZE = 64, FRAME_CLIENT_DATA_SIZE = 32, FRAME_EVENT_SIZE = 84, FRAME_WEAPON_ANIM_SIZE = 8, FRAME_SOUND_SIZE_1 = 8, FRAME_SOUND_SIZE_2 = 16, FRAME_DEMO_BUFFER_SIZE = 4, FRAME_NETMSG_SIZE = 468, FRAME_NETMSG_DEMOINFO_SIZE = 436, FRAME_NETMSG_MOVEVARS_SIZE = 32, FRAME_NETMSG_MIN_MESSAGE_LENGTH = 0, FRAME_NETMSG_MAX_MESSAGE_LENGTH = 65536 }; enum DemoHeader { netProtocol, demoProtocol, mapName[HEADER_MAPNAME_SIZE], gameDir[HEADER_GAMEDIR_SIZE], mapCRC, directoryOffset }; enum DemoEntry { dirEntryCount, type, description[DIR_ENTRY_DESCRIPTION_SIZE], flags, CDTrack, trackTime, frameCount, offset, fileLength, frames, ubuttons }; enum FrameHeader { Type, Float:Timestamp, Number }; enum NetMsgFrame { Float:timestamp, Float:view[3], viewmodel }; new iDemoEntry[DemoEntry]; new iDemoHeader[DemoHeader]; new iDemoFrame[FrameHeader]; public announce() { new datadir[128]; new filename[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(filename, charsmax(datadir), "%s/list_xj.txt", datadir); delete_file(filename); iXJWRs = fopen(filename, "wb"); new CURL:curl = curl_easy_init(); if(curl) { //curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_URL, "https://xtreme-jumps.eu/demos.txt"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, "write_xj"); curl_easy_perform(curl, "complite_xj"); } } public write_xj(data[], size, nmemb) { new real_size = size * nmemb; for(new i = 0; i < nmemb; i++) if(i < nmemb) fwrite(iXJWRs, data[i], BLOCK_BYTE); return real_size; } public complite_xj(CURLcode:code, CURL:curl) { curl_easy_cleanup(curl); fclose(iXJWRs); new datadir[128]; new filename[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(filename, charsmax(datadir), "%s/list_cc.txt", datadir); delete_file(filename); iCCWRs = fopen(filename, "wb"); new CURL:curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://cosy-climbing.net/demoz.txt"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, "write_cc"); curl_easy_perform(curl, "complite_cc"); } } public complite_cc(CURLcode:code, CURL:curl) { curl_easy_cleanup(curl); fclose(iCCWRs); new datadir[128]; new filename[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(filename, charsmax(datadir), "%s/list_kzru.txt", datadir); delete_file(filename); iKZRUWRs = fopen(filename, "wb"); new CURL:curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://kz-rush.ru/demos.txt"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, "write_kzru"); curl_easy_perform(curl, "complite_kzru"); } } public write_kzru(data[], size, nmemb) { new real_size = size * nmemb; for(new i = 0; i < nmemb; i++) if(i < nmemb) fwrite(iKZRUWRs, data[i], BLOCK_BYTE); return real_size; } public write_cc(data[], size, nmemb) { new real_size = size * nmemb; for(new i = 0; i < nmemb; i++) if(i < nmemb) fwrite(iCCWRs, data[i], BLOCK_BYTE); return real_size; } public complite_kzru(CURLcode:code, CURL:curl) { curl_easy_cleanup(curl); fclose(iKZRUWRs); OnDemosComplete(0); } public OnDemosComplete(Index) { new demoslist[128]; get_localinfo("amxx_datadir", demoslist, charsmax(demoslist)); format(demoslist, charsmax(demoslist), "%s/list_xj.txt", demoslist); new iDemosList = fopen(demoslist, "rb"); new ExplodedString[7][128]; new Line[128]; new MapName[64]; get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s ", MapName); while(!feof(iDemosList)) { 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) > -1) { bFoundDemo = true; break; } } if(!bFoundDemo) { get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s[", MapName); fseek(iDemosList, 0, SEEK_SET); while(!feof(iDemosList)) { fgets(iDemosList, Line, charsmax(Line)); ExplodeString(ExplodedString, 6, 127, Line, ' '); if(containi(ExplodedString[0], MapName) > -1) { bFoundDemo = true; break; } } } else { new Float:Date = str_to_float(ExplodedString[1]); new sWRTime[24]; fnConvertTime(Date, sWRTime, charsmax(sWRTime)); format(iArchiveName, charsmax(iArchiveName), "%s_%s_%s", ExplodedString[0], ExplodedString[2], sWRTime); StringTimer(Date, WR_TIME, sizeof(WR_TIME) - 1); WR_NAME = ExplodedString[2]; WR_COUNTRY = ExplodedString[3]; new iLink[512]; format(iLink, charsmax(iLink), "http://files.xtreme-jumps.eu/demos/%s.rar", iArchiveName); new datadir[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(datadir, charsmax(datadir), "%s/%s.rar", datadir, iArchiveName); WR_SRC = "XJ"; DownloadDemoArchive(iArchiveName, iLink); } if(!bFoundDemo) CheckCCList(); } public CheckCCList() { new demoslist[128]; get_localinfo("amxx_datadir", demoslist, charsmax(demoslist)); format(demoslist, charsmax(demoslist), "%s/list_cc.txt", demoslist); new iDemosList = fopen(demoslist, "rb"); new ExplodedString[7][128]; new Line[128]; new MapName[64]; get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s ", MapName); while(!feof(iDemosList)) { 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) > -1) { bFoundDemo = true; break; } } if(!bFoundDemo) { get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s[", MapName); fseek(iDemosList, 0, SEEK_SET); while(!feof(iDemosList)) { fgets(iDemosList, Line, charsmax(Line)); ExplodeString(ExplodedString, 6, 127, Line, ' '); if(containi(ExplodedString[0], MapName) > -1) { bFoundDemo = true; break; } } } else { new Float:Date = str_to_float(ExplodedString[1]); new sWRTime[24]; fnConvertTime(Date, sWRTime, charsmax(sWRTime)); format(iArchiveName, charsmax(iArchiveName), "%s_%s_%s", ExplodedString[0], ExplodedString[2], sWRTime); StringTimer(Date, WR_TIME, sizeof(WR_TIME) - 1); WR_NAME = ExplodedString[2]; WR_COUNTRY = ExplodedString[3]; new iLink[512]; 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); WR_SRC = "CC"; DownloadDemoArchive(iArchiveName, iLink); } if(!bFoundDemo) CheckKZRUList(); } public CheckKZRUList() { new demoslist[128]; get_localinfo("amxx_datadir", demoslist, charsmax(demoslist)); format(demoslist, charsmax(demoslist), "%s/list_kzru.txt", demoslist); new iDemosList = fopen(demoslist, "rb"); new ExplodedString[7][128]; new Line[128]; new MapName[64]; get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s ", MapName); while(!feof(iDemosList)) { 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) > -1) { bFoundDemo = true; break; } } if(!bFoundDemo) { get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s[", MapName); fseek(iDemosList, 0, SEEK_SET); while(!feof(iDemosList)) { fgets(iDemosList, Line, charsmax(Line)); ExplodeString(ExplodedString, 6, 127, Line, ' '); if(containi(ExplodedString[0], MapName) > -1) { bFoundDemo = true; break; } } } else { new Float:Date = str_to_float(ExplodedString[1]); new sWRTime[24]; fnConvertTime(Date, sWRTime, charsmax(sWRTime)); format(iArchiveName, charsmax(iArchiveName), "%s_%s_%s", ExplodedString[0], ExplodedString[2], sWRTime); StringTimer(Date, WR_TIME, sizeof(WR_TIME) - 1); WR_NAME = ExplodedString[2]; WR_COUNTRY = ExplodedString[3]; new iLink[512]; format(iLink, charsmax(iLink), "https://kz-rush.ru/xr_public/demos/maps/cs16/%s.zip", iArchiveName); new datadir[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(datadir, charsmax(datadir), "%s/%s.zip", datadir, iArchiveName); WR_SRC = "KZRU"; g_demoExt = "zip"; DownloadDemoArchive(iArchiveName, iLink); } } public DownloadDemoArchive(iArchiveName[], iLink[]) { new datadir[128]; new filename[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); new demodir[128], demodirfile[128]; format(demodir, charsmax(demodir), "%s/demos", datadir); format(demodirfile, charsmax(demodirfile), "%s/%s", demodir, g_szMapName); if(!dir_exists(demodir)) mkdir(demodir); if(!dir_exists(demodirfile)) mkdir(demodirfile); format(filename, charsmax(datadir), "%s/%s.%s", datadir, iArchiveName, g_demoExt); iArchive = fopen(filename, "wb"); new CURL:curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, iLink); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, "write_archive"); curl_easy_perform(curl, "complite_archive"); } } public write_archive(data[], size, nmemb) { new real_size = size * nmemb; for(new i = 0; i < nmemb; i++) if(i < nmemb) fwrite(iArchive, data[i], BLOCK_BYTE); return real_size; } public complite_archive(CURLcode:code, CURL:curl) { curl_easy_cleanup(curl); fclose(iArchive); OnArchiveComplete(); } public OnArchiveComplete() { new datadir[128], RARArchive[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(RARArchive, charsmax(RARArchive), "%s/%s.%s", datadir, iArchiveName, g_demoExt); server_print(" src: %s", WR_SRC); server_print(" rar: %s", RARArchive); AA_Unarchive(RARArchive, datadir, "@OnComplete", 0); } @OnComplete(id, iError) { new datadir[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(datadir, charsmax(datadir), "%s/%s.%s", datadir, iArchiveName, g_demoExt); delete_file(datadir); if(iError == AA_NO_ERROR) { new szNavName[256], demodir1[128], demodir2[128]; get_localinfo("amxx_datadir", datadir, charsmax(datadir)); format(szNavName, sizeof(szNavName), "%s", datadir, iArchiveName); format(demodir1, sizeof(demodir1), "%s/demos", szNavName); format(demodir2, sizeof(demodir2), "%s/demos/%s", szNavName, g_szMapName); if(!dir_exists(demodir1)) mkdir(demodir1); if(!dir_exists(demodir2)) mkdir(demodir2); format(iNavName, sizeof(iNavName), "%s/%s.nav", datadir, iArchiveName); format(iDemoName, sizeof(iDemoName), "%s/%s.dem", datadir, iArchiveName); if(!file_exists(iNavName)) { iFile = fopen(iDemoName, "rb"); if(iFile) { iParsedFile = fopen(iNavName, "w"); ReadHeaderX(); } } else LoadParsedInfo(iNavName); flStartTime = get_gametime(); } else server_print("Failed to unpack. Error code: %d", iError); } public 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; } public LoadParsedInfo(szNavName[]) { iFile = fopen(szNavName, "rb"); new Ent = engfunc(EngFunc_CreateNamedEntity , engfunc(EngFunc_AllocString, "info_target")); set_pev(Ent, pev_classname, "NavThink"); set_pev(Ent, pev_nextthink, get_gametime() + 0.01); } public ReadHeaderX() { if(IsValidDemoFile(iFile)) { ReadHeader(iFile); new Ent = engfunc(EngFunc_CreateNamedEntity , engfunc(EngFunc_AllocString, "info_target")); set_pev(Ent, pev_classname, "DemThink"); set_pev(Ent, pev_nextthink, get_gametime() + 0.01); } else server_print("demo is not valid!"); } public bool:IsValidDemoFile(file) { fseek(file, 0, SEEK_END); iDemo_header_size = ftell(file); if(iDemo_header_size < HEADER_SIZE) return false; fseek(file, 0, SEEK_SET); new signature[HEADER_SIGNATURE_CHECK_SIZE]; fread_blocks(file, signature, sizeof(signature), BLOCK_CHAR); if(!contain("HLDEMO", signature)) return false; return true; } public ReadHeader(file) { fseek(file, HEADER_SIGNATURE_SIZE, SEEK_SET); fread(file, iDemoHeader[demoProtocol], BLOCK_INT); fread(file, iDemoHeader[netProtocol], BLOCK_INT); fread_blocks(file, iDemoHeader[mapName], HEADER_MAPNAME_SIZE, BLOCK_CHAR); fread_blocks(file, iDemoHeader[gameDir], HEADER_GAMEDIR_SIZE, BLOCK_CHAR); fread(file, iDemoHeader[mapCRC], BLOCK_INT); fread(file, iDemoHeader[directoryOffset], BLOCK_INT); fseek(file, iDemoHeader[directoryOffset], SEEK_SET); fread(file, iDemoEntry[dirEntryCount], BLOCK_INT); for(new i = 0; i < iDemoEntry[dirEntryCount]; i++) { fread(file, iDemoEntry[type], BLOCK_INT); fread_blocks(file, iDemoEntry[description], DIR_ENTRY_DESCRIPTION_SIZE, BLOCK_CHAR); fread(file, iDemoEntry[flags], BLOCK_INT); fread(file, iDemoEntry[CDTrack], BLOCK_INT); fread(file, iDemoEntry[trackTime], BLOCK_INT); fread(file, iDemoEntry[frameCount], BLOCK_INT); fread(file, iDemoEntry[offset], BLOCK_INT); fread(file, iDemoEntry[fileLength], BLOCK_INT); } fseek(file, iDemoEntry[offset], SEEK_SET); } public ReadParsed(iEnt) { if(iFile) { new szLineData[512]; static sExplodedLine[11][150]; if(!feof(iFile)) { fseek(iFile, 0, SEEK_CUR); new iSeek = ftell(iFile); fseek(iFile, 0, SEEK_END); fseek(iFile, iSeek, SEEK_SET); fgets(iFile, szLineData, charsmax(szLineData)); ExplodeString(sExplodedLine, 10, 50, szLineData, '|'); if(equal(sExplodedLine[1], "ASD")) { new Keys = str_to_num(sExplodedLine[2]); new Float:Angles[3]; Angles[0] = str_to_float(sExplodedLine[3]); Angles[1] = str_to_float(sExplodedLine[4]); Angles[2] = 0.0; new Float:Origin[3]; Origin[0] = str_to_float(sExplodedLine[5]); Origin[1] = str_to_float(sExplodedLine[6]); Origin[2] = str_to_float(sExplodedLine[7]); new Float:velocity[3]; velocity[0] = str_to_float(sExplodedLine[8]); velocity[1] = str_to_float(sExplodedLine[9]); velocity[2] = 0.0; ArrayPushArray(fPlayerAngle, Angles); ArrayPushArray(fPlayerOrigin, Origin); ArrayPushArray(fPlayerVelo, velocity); ArrayPushCell(fPlayerKeys, Keys); } set_pev(iEnt, pev_nextthink, get_gametime() + 0.0001); return true; } else { server_print("Finished loading demo in %f sec.", get_gametime() - flStartTime); return false; } } return false; } public ReadFrames(file) { fseek(file, 0, SEEK_CUR); new iSeek = ftell(file); fseek(file, 0, SEEK_END); fseek(iFile, iSeek, SEEK_SET); static sum; if(!feof(file)) { new FrameType = ReadFrameHeader(file); new breakme; switch(FrameType) { case 0: { } case 1: { new Float:Origin[3], Float:ViewAngles[3], Float:velocity[3], iAsd[1024]; fseek(file, 4, SEEK_CUR); for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); for(new i = 0; i < 3; ++i) fread(file, _:ViewAngles[i], BLOCK_INT); fseek(file, 64, SEEK_CUR); for(new i = 0; i < 3; ++i) fread(file, _:velocity[i], BLOCK_INT); for(new i = 0; i < 3; ++i) fread(file, _:Origin[i], BLOCK_INT); fseek(file, 124, SEEK_CUR); for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 2, SEEK_CUR); fread(file, iDemoEntry[ubuttons], BLOCK_SHORT); format(iAsd, charsmax(iAsd), "%d|ASD|%d|%.4f|%.4f|%.3f|%.3f|%f|%.3f|%.3f|%.3f^n",sum, iDemoEntry[ubuttons], ViewAngles[0], ViewAngles[1], Origin[0],Origin[1],Origin[2], velocity[0], velocity[1], velocity[2]); fputs(iParsedFile, iAsd); fseek(file, 196, SEEK_CUR); new length; fread(file, length, BLOCK_INT); fseek(file, length, SEEK_CUR); } case 2: { } case 3: { new ConsoleCmd[FRAME_CONSOLE_COMMAND_SIZE]; fread_blocks(file, ConsoleCmd, FRAME_CONSOLE_COMMAND_SIZE, BLOCK_CHAR); } case 4: { sum++; for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); } case 5: { breakme = 2; } case 6: { fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); for(new i = 0; i < 3; ++i) fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); fseek(file, 4, SEEK_CUR); } case 7: { fseek(file, 8, SEEK_CUR); } case 8: { fseek(file, 4, SEEK_CUR); new length; fread(file, length, BLOCK_INT); new msg[128]; fread_blocks(file, msg, length, BLOCK_CHAR); fseek(file, 16, SEEK_CUR); } case 9: { new length = 0; fread(file, length, BLOCK_INT); new buffer[4]; fread_blocks(file, buffer, length, BLOCK_BYTE); } default: { breakme = 2; } } if(breakme == 2) return true; } return false; } public ReadFrameHeader(file) { fread(file, iDemoFrame[Type], BLOCK_BYTE); fread(file, _:iDemoFrame[Timestamp], BLOCK_INT); fread(file, iDemoFrame[Number], BLOCK_INT); return(iDemoFrame[Type]); } public 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); } public parsing_country(data[]) { new demoslist[128]; get_localinfo("amxx_datadir", demoslist, charsmax(demoslist)); if(equali(data, "xj")) format(demoslist, charsmax(demoslist), "%s/list_xj.txt", demoslist); else if(equali(data, "cc")) format(demoslist, charsmax(demoslist), "%s/list_cc.txt", demoslist); new iDemosList = fopen(demoslist, "rb"); new ExplodedString[7][128]; new Line[128]; new MapName[64]; get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s ", MapName); while(!feof(iDemosList)) { 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) > -1) { g_Demos = true; break; } } if(!g_Demos) { get_mapname(MapName, 63); format(MapName, charsmax(MapName), "%s[", MapName); fseek(iDemosList, 0, SEEK_SET); while(!feof(iDemosList)) { fgets(iDemosList, Line, charsmax(Line)); ExplodeString(ExplodedString, 6, 127, Line, ' '); if(containi(ExplodedString[0], MapName) > -1) { g_Demos = true; break; } } } else { new FLAG[10]; formatex(FLAG, charsmax(FLAG), "%s", ExplodedString[3]); trim(FLAG); if(equali(FLAG, "")) FLAG = "xz"; if(equali(FLAG, "n-")) FLAG = "xz"; formatex(url_sprite, charsmax(url_sprite), "sprites/wrbot/%s.spr", FLAG); formatex(url_sprite_xz, charsmax(url_sprite_xz), "sprites/wrbot/xz.spr"); if(file_exists(url_sprite)) precache_model(url_sprite); else if(file_exists(url_sprite_xz)) precache_model(url_sprite_xz); else return; } if(!g_Demos && equali(data, "xj")) parsing_country("cc"); } public client_connect(id) { if(is_user_bot(id)) return; } stock StringTimer(const Float:flRealTime, szOutPut[], const iSizeOutPut) { static Float:flTime, iMinutes, iSeconds, iMiliSeconds, Float:iMili; new string[12]; flTime = flRealTime; if(flTime < 0.0) flTime = 0.0; iMinutes = floatround(flTime / 60, floatround_floor); iSeconds = floatround(flTime - (iMinutes * 60), floatround_floor); iMili = floatfract(flRealTime); formatex(string, 11, "%.02f", iMili >= 0 ? iMili + 0.005 : iMili - 0.005); iMiliSeconds = floatround(str_to_float(string) * 100, floatround_floor); formatex(szOutPut, iSizeOutPut, "%02d:%02d.%02d", iMinutes, iSeconds, iMiliSeconds); }