HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /************************************************************************************************
  2. *
  3. * Potti v1.40, by p3tsin | Fordittota: SmaCk
  4. *
  5. *************************************************************************************************
  6. *
  7. * Leiras:
  8. * Lehetove teszi a plugin, hogy adminok hozzanak letre botokat, es azokat menubol iranyitsak.
  9. *
  10. *
  11. * Parancsok:
  12. * amx_botadd <name> - Uj bot letrehozasa
  13. * amx_botexec <cmd> - Parancs vegrehajtas a botokon
  14. * amx_botmove <0-3> - 0: ki
  15. * 1: masolja a mozgasokat
  16. * 2: ugyanaz mint #1 + celja ugyanazon a helyen
  17. * 3: Nezd az ellenkezo utat, es az ellenkezo mozgast
  18. * amx_botcmds <1/0> - ha engedelyezve, minden tulajdonos tudja iranyitani az O botjat
  19. * amx_botdel - Bot kirugasa a szerverrol
  20. *
  21. * Server cvarok:
  22. * potti_hudcolor <r g b> - Megvaltoztatja a szinet HUD uzenetnek
  23. * potti_hudpos <x y> - Megvaltoztatja a helyzetet HUD uzenetnek
  24. *
  25. * Fontos:
  26. * Amikor a parancsok vegrehajtasa van, csak a "motor" parancs fog mukodni.
  27. * Az is javaslat, hogy kotodnek a gombok "messagemode amx_botexec",
  28. * Az lesz konnyeb iranyitas, mint a konzolbol :)
  29. *
  30. *
  31. * Folytatas:
  32. * - Semmi kulonos (Nem erzem magam, mint egy Messias)
  33. *
  34. * Ismert hibak:
  35. * - (cs) amikor a tulaj halott, a csapatmenu megnyilik, es az igazan bosszanto :(
  36. * - (cs) Nem tudja megnyitni vasarlasi zonat, mikozben botokat kezeli
  37. *
  38. *
  39. * Fejlesztesi log:
  40. * 1.00 - Elso Kiadas
  41. * 1.10 - Hozzaadott teljes vezerlesi mod
  42. * - Shows money left on a bot when a buymenu is opened
  43. * 1.20 - Modified so everyone (with access) can have their own bot
  44. * - Cstrike-module is no more needed to display money
  45. * - After dying, the owner will automatically move to spectating to his/her bot if botmove is on
  46. * - Messages printed to a bot (to center and chat) are shown to its owner too
  47. * - Fixed bot latency to show as "BOT"
  48. * - More efficient msec calculations
  49. * - Other little improvements
  50. * 1.30 - Added support for The Specialists (press 6 to switch to kungfu when in fullcontrol mode)
  51. * - Added botmove 3 to make the bot do the opposite of the owner
  52. * - Added a hudtext to show player health, weapon, etc.
  53. * - Access level changed from "m" to "p" ^_^
  54. * - Removed mod specific definitions
  55. * 1.40 - Changed owner input hooking style, making it possible for bots to walk and use impulses (flashlight, spray, ..)
  56. * - A little tweaking here and there
  57. *
  58. *
  59. * Segitsegek:
  60. * Botman - Sokat Segitett
  61. * Lord of Destruction - aim_at_origin() base taken from set_client_aiming()
  62. * THE_STORM - hatekonyabb szamitasok (from ePODbot)
  63. * strelomet - kijelzo bot "BOT" (from YaPB)
  64. * Orangutanz - koszonet a nehany hibamert ;)
  65. * Karko - koszonjuk, hogy segitett a TS tamogatasban
  66. *
  67. *
  68. ************************************************************************************************/
  69.  
  70.  
  71. #define ACCESS ADMIN_LEVEL_D //access level for bot commands, D is "p" in users.ini
  72. #define HUD_CHANNEL 4 //hud channel for showing bot info
  73.  
  74. #include <amxmodx>
  75. #include <amxmisc>
  76. #include <fakemeta>
  77.  
  78. new const plugin[] = "Potti"
  79. new const version[] = "1.40"
  80. new const author[] = "p3tsin"
  81.  
  82. new using_mod //1: cstrike, 2: specialists, 0: other
  83. new money_offset //didnt want to include cstrike just for cs_get_user_money, so i used fakemeta
  84.  
  85. new botindex[33], botowner[33]
  86. new botinfo[33], hasmenu[33]
  87. new copymovements[33]
  88. new bool:fullcontrol[33]
  89.  
  90. new Float:botmove[33][3]
  91. new Float:botangles[33][3]
  92. new botbuttons[33]
  93. new botimpulses[33]
  94.  
  95. new botsnum
  96. new gMsg_ShowMenu
  97. new gMsg_TextMsg
  98.  
  99. new cv_hudcolor
  100. new cv_hudpos
  101.  
  102. new fow_serverframe
  103. new fow_cmdstart
  104. new fow_clientkill
  105.  
  106. /* botinfos */
  107. enum {
  108. info_none = 0,
  109. info_motd
  110. }
  111.  
  112. new slotsnum
  113. new slotmenukeys
  114. new currentweapon[33][3]
  115. new weapon_slots[6][32]
  116.  
  117. const TASK_BOTINFO = 54387 //random task id for check_botinfo
  118.  
  119. /* commands which are not blocked/executed in fullcontrol mode */
  120. new const fullcontrol_cmds[7][] = {
  121. "amx_botadd", "amx_botexec", "amx_botmove", "amx_botcmds", "amx_botdel",
  122. "specmode", "follow"
  123. }
  124.  
  125. // ================================================================================================
  126. // ================================================================================================
  127.  
  128. #define get_user_money(%1) get_pdata_int(%1,money_offset)
  129. #define Distance2D(%1,%2) floatsqroot((%1*%1) + (%2*%2))
  130. #define Radian2Degree(%1) (%1 * 180.0 / M_PI) //(%1 * 360.0 / (2 * M_PI))
  131.  
  132. // ================================================================================================
  133. // ================================================================================================
  134.  
  135. public plugin_init() {
  136. register_plugin(plugin,version,author)
  137. register_clcmd("amx_botadd", "makebot",ACCESS, "<name> - Uj bot hozzaadasa")
  138. register_clcmd("amx_botexec", "execbot",ACCESS, "<cmd> - Parancs vegrehajtas a botokon")
  139. register_clcmd("amx_botmove", "movebot",ACCESS, "<0-2> - Bot mozgasok")
  140. register_clcmd("amx_botcmds", "cmdsbot",ACCESS, "<0/1> - Minden parancs kuldese botoknak")
  141. register_clcmd("amx_botdel", "removebot",ACCESS, "- Bot kirugasa")
  142.  
  143. register_clcmd("say", "catch_say")
  144. register_clcmd("say_team", "catch_say")
  145.  
  146. static mod[20]
  147. get_modname(mod,19)
  148. if(equal(mod,"cstrike") || equal(mod,"czero") || equal(mod,"csv15") || equal(mod,"cs13")) using_mod = 1
  149. else if(equal(mod,"ts")) using_mod = 2
  150.  
  151. register_event("DeathMsg", "event_deathmsg", "a")
  152. register_event("MOTD", "event_motd", "b")
  153. register_event("ResetHUD", "event_resethud", "be")
  154. register_event("ShowMenu", "event_showmenu", "b")
  155. register_event("TextMsg", "event_textmsg", "b", "1=4") //take only print_center
  156.  
  157. switch(using_mod) { //mod specific events
  158. case 1: register_event("Spectator", "event_spectator", "a", "2=1")
  159. case 2: {
  160. register_event("ClipInfo", "event_clipinfo", "be")
  161. register_event("WeaponInfo", "event_weaponinfo", "be") //ts_getuserwpn didnt work right (for a bot)
  162. register_event("WStatus", "event_wstatus", "be") //updates pev_weapons to make slotmenu work
  163. }
  164. }
  165.  
  166. gMsg_ShowMenu = get_user_msgid("ShowMenu")
  167. gMsg_TextMsg = get_user_msgid("TextMsg")
  168.  
  169. cv_hudcolor = register_cvar("potti_hudcolor","50 150 200")
  170. cv_hudpos = register_cvar("potti_hudpos","0.82 0.85")
  171. }
  172.  
  173. public plugin_cfg() {
  174. switch(using_mod) { //mod specific weapons and other settings
  175. case 1: {
  176. slotsnum = 5
  177. set_weaponslot(1,{ 3,5,7,8,12,13,14,15,18,19,20,21,22,23,24,27,28,30,0 })
  178. set_weaponslot(2,{ 1,10,11,16,17,26,0 })
  179. set_weaponslot(3,{ 29,0 })
  180. set_weaponslot(4,{ 4,9,25,0 })
  181. set_weaponslot(5,{ 6,0 })
  182. money_offset = is_amd64_server() ? 140 : 115
  183. }
  184. case 2: {
  185. slotsnum = 6
  186. set_weaponslot(1,{ 24,25,34,35,0 })
  187. set_weaponslot(2,{ 1,9,12,14,22,28,31,0 })
  188. set_weaponslot(3,{ 3,6,7,17,19,23,0 })
  189. set_weaponslot(4,{ 4,5,11,13,15,18,20,26,27,32,33,0 })
  190. set_weaponslot(5,{ 8,10,16,21,30,0 })
  191. set_weaponslot(6,{ 36,0 }) //kungfu id is 0, so i had to make a special case for it
  192. }
  193. // default: slotsnum = 0
  194. }
  195. for(new i = 0; i < slotsnum; i++) slotmenukeys |= (1<<i)
  196. }
  197.  
  198. set_weaponslot(slot,weapons[]) {
  199. slot--
  200. new len = strlen(weapons)
  201. for(new i = 0; i < len; i++) weapon_slots[slot][i] = weapons[i]
  202. }
  203.  
  204. public client_disconnect(id) {
  205. if(is_user_bot(id)) {
  206. new owner = botowner[id]
  207. if(owner) {
  208. copymovements[owner] = 0, botowner[id] = 0
  209. botindex[owner] = 0
  210. if(!--botsnum) bot_delforwards()
  211. }
  212. }
  213. else {
  214. new bot = botindex[id]
  215. if(is_user_connected(bot)) server_cmd("kick #%d",get_user_userid(bot))
  216. fullcontrol[id] = false, copymovements[id] = 0
  217. hasmenu[id] = 0, botindex[id] = 0
  218. }
  219. }
  220.  
  221. // ================================================================================================
  222. // ================================================================================================
  223.  
  224. public makebot(id,level,cid) {
  225. if(!cmd_access(id,level,cid,2))
  226. return PLUGIN_HANDLED
  227.  
  228. if(is_user_connected(botindex[id])) {
  229. console_print(id, "[%s] You already have a bot connected!",plugin)
  230. return PLUGIN_HANDLED
  231. }
  232.  
  233. static name[32]
  234. read_args(name,31)
  235. remove_quotes(name)
  236. trim(name)
  237. new bot = engfunc(EngFunc_CreateFakeClient,name)
  238. if(!bot) {
  239. console_print(id, "[%s] Nem sikerult letrehozni botot, szerver tele van?",plugin)
  240. return PLUGIN_HANDLED
  241. }
  242.  
  243. engfunc(EngFunc_FreeEntPrivateData,bot)
  244. bot_settings(bot)
  245.  
  246. if(!botsnum) bot_addforwards()
  247.  
  248. static szRejectReason[128]
  249. dllfunc(DLLFunc_ClientConnect,bot,name,"127.0.0.1",szRejectReason)
  250. if(!is_user_connected(bot)) {
  251. if(!botsnum) bot_delforwards()
  252. console_print(id, "[%s] Csatlakozast elutasitottak: %s",plugin,szRejectReason)
  253. return PLUGIN_HANDLED
  254. }
  255.  
  256. dllfunc(DLLFunc_ClientPutInServer,bot)
  257. set_pev(bot,pev_spawnflags, pev(bot,pev_spawnflags) | FL_FAKECLIENT)
  258. set_pev(bot,pev_flags, pev(bot,pev_flags) | FL_FAKECLIENT)
  259.  
  260. reset_controls(id)
  261. fullcontrol[id] = false, copymovements[id] = 0
  262. botindex[id] = bot, botowner[bot] = id
  263. hasmenu[id] = 0, botsnum++
  264.  
  265. console_print(id, "[%s] Bot sikeresen hozzaadva! Id: %d, Nev: %s",plugin,bot,name)
  266. return PLUGIN_HANDLED
  267. }
  268.  
  269. public execbot(id,level,cid) {
  270. if(!cmd_access(id,level,cid,2))
  271. return PLUGIN_HANDLED
  272.  
  273. new bot = botindex[id]
  274. if(!is_user_connected(bot)) {
  275. console_print(id, "[%s] Nincs bot csatlakoztatva..",plugin)
  276. return PLUGIN_HANDLED
  277. }
  278.  
  279. static cmd[32], name[32]
  280. read_argv(1, cmd,31)
  281. get_user_name(bot, name,31)
  282.  
  283. if(equal(cmd,"say") || equal(cmd,"say_team")) {
  284. static saytext[128], team
  285. new len = strlen(cmd) + 1
  286. read_args(saytext,127)
  287. if(equal(cmd,"say_team")) team = 1
  288. bot_say(bot,team,saytext[len])
  289. console_print(id, "[%s] Vegrehajtott %s: %s %s",plugin,name,cmd,saytext)
  290. return PLUGIN_HANDLED
  291. }
  292.  
  293. static args[2][32]
  294. new num = read_argc()-2
  295. args[0][0] = 0, args[1][0] = 0
  296. for(new i = 0; i < num; i++) read_argv(i+2, args[i],31)
  297.  
  298. if(equal(cmd,"kill")) dllfunc(DLLFunc_ClientKill, bot)
  299. else if(equal(cmd,"name")) set_user_info(bot,"name",args[0])
  300. else if(equal(cmd,"model")) set_user_info(bot,"model",args[0])
  301. else bot_command(bot,cmd,args[0],args[1])
  302.  
  303. console_print(id, "[%s] Vegrehajtott %s: %s %s %s",plugin,name,cmd,args[0],args[1])
  304. return PLUGIN_HANDLED
  305. }
  306.  
  307. public movebot(id,level,cid) {
  308. if(!cmd_access(id,level,cid,2))
  309. return PLUGIN_HANDLED
  310.  
  311. if(!is_user_connected(botindex[id])) {
  312. console_print(id, "[%s] Nincs bot csatlakoztatva..",plugin)
  313. return PLUGIN_HANDLED
  314. }
  315.  
  316. static arg[2], message[64]
  317. read_argv(1, arg,1)
  318.  
  319. new num = str_to_num(arg)
  320. if(num < 0 || num > 3) num = 0
  321.  
  322. switch(num) {
  323. case 0: formatex(message,63, "not copying your moves at all")
  324. case 1: formatex(message,63, "copying your movements")
  325. case 2: formatex(message,63, "copying your movements and aiming the same spot when shooting")
  326. case 3: formatex(message,63, "copying your movements in reverse mode")
  327. }
  328.  
  329. copymovements[id] = num
  330. console_print(id, "[%s] A bot most %s",plugin,message)
  331. return PLUGIN_HANDLED
  332. }
  333.  
  334. public cmdsbot(id,level,cid) {
  335. if(!cmd_access(id,level,cid,2))
  336. return PLUGIN_HANDLED
  337.  
  338. if(!is_user_connected(botindex[id])) {
  339. console_print(id, "[%s] Nincs bot csatlakoztatva..",plugin)
  340. return PLUGIN_HANDLED
  341. }
  342.  
  343. new arg[2]
  344. read_argv(1, arg,1)
  345. new bool:value = str_to_num(arg) ? true : false
  346.  
  347. fullcontrol[id] = value
  348. console_print(id, "[%s] Fullcontrol mod: %s",plugin,value?"ON (nem tudod iranyitani magad most)":"OFF")
  349. slotmenu(id,value)
  350. return PLUGIN_HANDLED
  351. }
  352.  
  353. public removebot(id,level,cid) {
  354. if(!cmd_access(id,level,cid,1))
  355. return PLUGIN_HANDLED
  356.  
  357. new bot = botindex[id]
  358. if(is_user_connected(bot)) {
  359. static name[32]
  360. get_user_name(bot, name,31)
  361. console_print(id, "[%s] Bot %s kicked!",plugin,name)
  362. server_cmd("kick #%d",get_user_userid(bot))
  363. }
  364. else console_print(id, "[%s] Nincs bot csatlakoztatva..",plugin)
  365. return PLUGIN_HANDLED
  366. }
  367.  
  368. // ================================================================================================
  369. // ================================================================================================
  370.  
  371. public check_botinfo() {
  372. static text[192], len, weapon
  373. static players[32], inum, bot, owner
  374. get_players(players,inum, "dh")
  375.  
  376. static temp[3][10], color[3], Float:pos[2], i
  377. get_pcvar_string(cv_hudcolor, text,20)
  378. parse(text, temp[0],3, temp[1],3, temp[2],3)
  379. for(i = 0; i < 3; i++) color[i] = str_to_num(temp[i])
  380.  
  381. get_pcvar_string(cv_hudpos, text,20)
  382. parse(text, temp[0],9, temp[1],9)
  383. for(i = 0; i < 2; i++) pos[i] = floatstr(temp[i])
  384.  
  385. new Float:holdtime = (using_mod == 2) ? 120.0 : 1.0 //TS handles hudmessages differently
  386. set_hudmessage(color[0],color[1],color[2], pos[0],pos[1], 0, 0.0, holdtime, 0.0, 0.2, HUD_CHANNEL)
  387.  
  388. static bool:was_alive[33]
  389. static name[32], weaponname[20], clip, ammo
  390. for(i = 0; i < inum; i++) {
  391. bot = players[i], owner = botowner[players[i]]
  392. if(!owner) continue //no owner, so this might be some other bot :o
  393.  
  394. switch(botinfo[owner]) {
  395. case info_motd: {
  396. set_pev(bot,pev_button,IN_ATTACK)
  397. client_print(owner,print_chat, "[%s] Fontos: Egy MOTD ablak zarva volt bot kozben",plugin)
  398. }
  399. }
  400. botinfo[owner] = info_none
  401.  
  402. if(!is_user_alive(bot)) {
  403. if(was_alive[bot]) { //hide hudmessage after death (mainly for TS)
  404. show_hudmessage(owner,"^n")
  405. was_alive[bot] = false
  406. }
  407. continue
  408. }
  409. was_alive[bot] = true
  410.  
  411. if(using_mod == 2) weapon = get_ts_weapon(bot,clip,ammo)
  412. else weapon = get_user_weapon(bot,clip,ammo)
  413.  
  414. get_user_name(bot, name,31)
  415. get_weaponname(weapon, weaponname,19)
  416. if(using_mod == 1) copy(weaponname,19, weaponname[7]) //cut off the "weapon_" tag
  417.  
  418. len = formatex(text,191, "Nev: %s, Elet: %d",name,get_user_health(bot))
  419. len += formatex(text[len],191-len, "^nFegyver: %s, Loszer: %d/%d",weaponname,clip,ammo)
  420.  
  421. if(using_mod == 1) formatex(text[len],191-len, "^nPenz maradt: $%d",get_user_money(bot))
  422. show_hudmessage(owner,"%s",text)
  423. }
  424. }
  425.  
  426. public client_command(id) {
  427. new bot = botindex[id]
  428. if(!bot) return PLUGIN_CONTINUE
  429.  
  430. static cmd[32]
  431. read_argv(0, cmd,31)
  432.  
  433. new menu = hasmenu[id]
  434. if(menu && equal(cmd,"menuselect")) {
  435. new num[3] //no need to check if menu even has this key,
  436. read_argv(1, num,2) //coz menuselect wont be called if it doesnt
  437.  
  438. hasmenu[id] = 0
  439. if(fullcontrol[id]) slotmenu(id,true)
  440.  
  441. switch(menu) {
  442. case 1: engclient_cmd(bot,"menuselect",num)
  443. case 2: change_to_weapon(bot,str_to_num(num))
  444. }
  445. return PLUGIN_HANDLED
  446. }
  447. else if(fullcontrol[id]) {
  448. new num = sizeof(fullcontrol_cmds)
  449. for(new i = 0; i < num; i++) {
  450. if(!equali(cmd,fullcontrol_cmds[i])) continue
  451. return PLUGIN_CONTINUE
  452. }
  453.  
  454. if(!contain(cmd,"say")) {
  455. static saytext[128], team
  456. read_args(saytext,127)
  457. remove_quotes(saytext)
  458. if(equal(cmd,"say_team")) team = 1
  459. bot_say(bot,team,saytext)
  460. }
  461. else {
  462. static arg1[32], arg2[32]
  463. read_argv(1, arg1,95)
  464. read_argv(2, arg2,31)
  465. bot_command(bot,cmd,arg1,arg2)
  466. }
  467. return PLUGIN_HANDLED
  468. }
  469. return PLUGIN_CONTINUE
  470. }
  471.  
  472. // ================================================================================================
  473. // ================================================================================================
  474.  
  475. public fm_cmdstart(id,uc_handle,random_seed) {
  476. new bot = botindex[id], movement = copymovements[id]
  477. if(!bot || !movement) return FMRES_IGNORED
  478.  
  479. new alive = is_user_alive(id), button = get_uc(uc_handle,UC_Buttons)
  480. if(!alive) set_uc(uc_handle,UC_Buttons, button & ~IN_JUMP & ~IN_ATTACK & ~IN_ATTACK2 & ~IN_FORWARD & ~IN_BACK & ~IN_MOVELEFT & ~IN_MOVERIGHT)
  481.  
  482. if(is_user_alive(bot)) {
  483. get_uc(uc_handle,UC_ForwardMove, botmove[id][0])
  484. get_uc(uc_handle,UC_SideMove, botmove[id][1])
  485. get_uc(uc_handle,UC_UpMove, botmove[id][2])
  486.  
  487. static Float:angles[3]
  488. if(movement == 2 && alive && button&IN_ATTACK) {
  489. static Float:target[3]
  490. get_user_aim(id,target)
  491. aim_at_origin(bot,target,angles)
  492. }
  493. else {
  494. get_uc(uc_handle,UC_ViewAngles, angles)
  495. if(movement == 3 && alive) {
  496. angles[1] += (angles[1] < 180.0) ? 180.0 : -180.0
  497. if(button&IN_JUMP) button = button & ~IN_JUMP | IN_DUCK
  498. else if(button&IN_DUCK) button = button & ~IN_DUCK | IN_JUMP
  499. }
  500. }
  501. botangles[id][0] = angles[0]
  502. botangles[id][1] = angles[1]
  503. botangles[id][2] = angles[2]
  504. botbuttons[id] = button
  505. botimpulses[id] = get_uc(uc_handle,UC_Impulse)
  506. }
  507. return FMRES_IGNORED
  508. }
  509.  
  510. public fm_serverframe() {
  511. static players[32], inum
  512. get_players(players,inum, "dh")
  513.  
  514. static Float:msecval
  515. global_get(glb_frametime, msecval)
  516. new msec = floatround(msecval * 1000.0)
  517.  
  518. static bot, owner, Float:angles[3]
  519. for(new i = 0; i < inum; i++) {
  520. bot = players[i], owner = botowner[bot]
  521. if(!owner) continue //no owner, so this might be some other bot :o
  522.  
  523. if(is_user_alive(bot)) {
  524. angles[0] = botangles[owner][0]
  525. angles[1] = botangles[owner][1]
  526. angles[2] = botangles[owner][2]
  527.  
  528. set_pev(bot,pev_v_angle,angles)
  529. angles[0] /= -3.0
  530. set_pev(bot,pev_angles,angles)
  531. }
  532. engfunc(EngFunc_RunPlayerMove,bot,angles,botmove[owner][0],botmove[owner][1],botmove[owner][2],botbuttons[owner],botimpulses[owner],msec)
  533. }
  534. return FMRES_IGNORED
  535. }
  536.  
  537. public fm_clientkill(id) {
  538. new bot = botindex[id]
  539. if(bot && fullcontrol[id]) {
  540. if(is_user_alive(bot)) dllfunc(DLLFunc_ClientKill, bot)
  541. else console_print(id, "[%s] Nem lehet ongyilkossag -- a bot mar halott",plugin)
  542. return FMRES_SUPERCEDE
  543. }
  544. return FMRES_IGNORED
  545. }
  546.  
  547. // ================================================================================================
  548. // ================================================================================================
  549.  
  550. public catch_say(id) {
  551. if(!botsnum) return
  552.  
  553. static cmd[10], said[128]
  554. read_argv(0, cmd,9)
  555. read_args(said,127)
  556. remove_quotes(said)
  557.  
  558. new teamsay = equal(cmd,"say_team") ? 1 : 0
  559. handle_saytext(id,said,teamsay)
  560. }
  561.  
  562. public event_deathmsg() {
  563. new id = read_data(2)
  564. if(!botindex[id]) {
  565. id = botowner[id]
  566. if(id) reset_controls(id)
  567. return
  568. }
  569.  
  570. new len
  571. static message[128]
  572. if(copymovements[id]) len = formatex(message,127, "botmove (you can't control yourself completely), ")
  573.  
  574. if(fullcontrol[id]) len += formatex(message[len],127-len, "botcmds (all of your commands are sent to the bot)")
  575. else if(len) message[len-2] = 0
  576.  
  577. if(len) ucfirst(message)
  578. else formatex(message,127, "Egyiksem")
  579.  
  580. client_print(id,print_chat, "[%s] Te a kovetkezo modot engedelyezted:",plugin)
  581. client_print(id,print_chat, "* %s",message)
  582. }
  583.  
  584. public event_motd(id) {
  585. new owner = botowner[id]
  586. if(owner) botinfo[owner] = info_motd
  587. }
  588.  
  589. public event_resethud(id) {
  590. new owner = botowner[id]
  591. if(owner) {
  592. client_print(owner,print_chat, "[%s] A bot ujraeledt",plugin)
  593. if(using_mod == 2) {
  594. set_pev(id,pev_weapons,0)
  595. currentweapon[id][0] = 0
  596. currentweapon[id][1] = 0
  597. currentweapon[id][2] = 0
  598. }
  599. }
  600. }
  601.  
  602. public event_showmenu(id) {
  603. new owner = botowner[id]
  604. if(!owner) return
  605.  
  606. static menu[32]
  607. new keys = read_data(1)
  608. read_data(4, menu,31)
  609. if(!strlen(menu)) return
  610.  
  611. hasmenu[owner] = 1 //keypress is catched in client_command()
  612. message_begin(MSG_ONE,gMsg_ShowMenu,{0,0,0},owner)
  613. write_short(keys)
  614. write_char(-1)
  615. write_byte(0)
  616. write_string(menu)
  617. message_end()
  618.  
  619. client_print(owner,print_chat, "[%s] A menun nyilt meg a bot: %s",plugin,menu)
  620. }
  621.  
  622. public event_spectator() {
  623. new id = read_data(1)
  624. if(copymovements[id]) {
  625. client_cmd(id, "specmode 4") //first person
  626. set_task(0.3,"next_spectarget",id)
  627. }
  628. }
  629.  
  630. public next_spectarget(id) {
  631. new bot = botindex[id]
  632. if(is_user_alive(bot)) {
  633. static name[32]
  634. get_user_name(bot, name,31)
  635. client_cmd(id, "follow ^"%s^"",name)
  636. }
  637. }
  638.  
  639. public event_textmsg(id) {
  640. new owner = botowner[id]
  641. if(!owner || !is_user_alive(id)) return
  642.  
  643. static message[32]
  644. new datanum = read_datanum()
  645. read_data(2, message,31)
  646.  
  647. message_begin(MSG_ONE,gMsg_TextMsg,{0,0,0},owner)
  648. write_byte(4)
  649. write_string(message)
  650.  
  651. for(new i = 3; i < datanum; i++) {
  652. read_data(i, message,31)
  653. write_string(message)
  654. }
  655.  
  656. message_end()
  657. return
  658. }
  659.  
  660. public event_clipinfo(id) {
  661. if(botowner[id]) currentweapon[id][1] = read_data(1)
  662. }
  663.  
  664. public event_weaponinfo(id) {
  665. if(botowner[id]) {
  666. currentweapon[id][0] = read_data(1)
  667. currentweapon[id][1] = read_data(2)
  668. currentweapon[id][2] = read_data(3)
  669. }
  670. }
  671.  
  672. public event_wstatus(id) {
  673. new owner = botowner[id]
  674. if(!owner) return
  675.  
  676. new wp = read_data(1), status = read_data(2)
  677. new wlist = pev(id,pev_weapons), weapon = (1<<wp)
  678. if(status) set_pev(id,pev_weapons, wlist | weapon)
  679. else set_pev(id,pev_weapons, wlist & ~weapon)
  680. return
  681. }
  682.  
  683. // ================================================================================================
  684. // ================================================================================================
  685.  
  686. stock get_user_aim(id,Float:aimorig[3]) {
  687. static Float:origin[3], Float:view_ofs[3]
  688. pev(id,pev_origin, origin)
  689. pev(id,pev_view_ofs, view_ofs)
  690. origin[0] += view_ofs[0]
  691. origin[1] += view_ofs[1]
  692. origin[2] += view_ofs[2]
  693.  
  694. static Float:vec[3]
  695. pev(id,pev_v_angle, vec)
  696. engfunc(EngFunc_MakeVectors,vec)
  697. global_get(glb_v_forward,vec)
  698. vec[0] = origin[0] + vec[0] * 9999.0
  699. vec[1] = origin[1] + vec[1] * 9999.0
  700. vec[2] = origin[2] + vec[2] * 9999.0
  701.  
  702. static line
  703. engfunc(EngFunc_TraceLine,origin,vec,0,id,line)
  704. get_tr2(line,TR_vecEndPos, aimorig)
  705. }
  706.  
  707. stock aim_at_origin(id,const Float:origin[3],Float:angles[3]) { //stock base by Lord of Destruction
  708. static Float:DeltaOrigin[3], Float:orig[3]
  709. pev(id,pev_origin, orig)
  710. DeltaOrigin[0] = orig[0] - origin[0]
  711. DeltaOrigin[1] = orig[1] - origin[1]
  712. DeltaOrigin[2] = orig[2] - origin[2] + 16.0 //bot keeps aiming too high
  713.  
  714. angles[0] = Radian2Degree(floatatan(DeltaOrigin[2] / Distance2D(DeltaOrigin[0], DeltaOrigin[1]),0))
  715. angles[1] = Radian2Degree(floatatan(DeltaOrigin[1] / DeltaOrigin[0],0))
  716. if(DeltaOrigin[0] >= 0.0) angles[1] += 180.0
  717. }
  718.  
  719. stock change_to_weapon(id,slot) {
  720. if(slot > slotsnum) return 0
  721.  
  722. if(using_mod == 2 && slot == 6) {
  723. engclient_cmd(id,"weapon_0")
  724. return 1
  725. }
  726.  
  727. new wnum
  728. static weapons[32], a
  729. get_user_weapons(id,weapons,wnum)
  730. new weapon, num = strlen(weapon_slots[--slot])
  731.  
  732. for(new i = 0; i < wnum; i++) {
  733. for(a = 0; a < num; a++) {
  734. if(weapons[i] != weapon_slots[slot][a]) continue
  735. weapon = weapons[i]
  736. break
  737. }
  738. if(weapon) break
  739. }
  740.  
  741. if(weapon) {
  742. static weaponname[20]
  743. if(using_mod == 2) formatex(weaponname,19, "weapon_%d",weapon)
  744. else get_weaponname(weapon,weaponname,19)
  745. engclient_cmd(id,weaponname)
  746. return 1
  747. }
  748. return 0
  749. }
  750.  
  751. stock get_ts_weapon(id,&clip,&ammo) {
  752. if(!is_user_bot(id)) return 0
  753. clip = currentweapon[id][1]
  754. ammo = currentweapon[id][2]
  755. return currentweapon[id][0]
  756. }
  757.  
  758. // ================================================================================================
  759. // ================================================================================================
  760.  
  761. handle_saytext(id,said[],teamsay) {
  762. static name[32], text[192], teamname[20]
  763. get_user_name(id, name,31)
  764.  
  765. new len, alive = is_user_alive(id)
  766. if(!alive) len = formatex(text,191, "*DEAD*")
  767. if(teamsay) {
  768. get_user_team(id, teamname,19)
  769. len += formatex(text[len],191-len, "(%s)",teamname)
  770. }
  771. else teamname[0] = 0
  772.  
  773. if(len) text[len++] = ' ' //add a space ;)
  774. formatex(text[len],191-len, "%s : %s",name,said)
  775.  
  776. static players[32], inum, owner, flags[5]
  777. formatex(flags,4, "dh%c%c",alive ? 'a' : 'b',teamsay ? 'e' : 0)
  778. get_players(players,inum, flags,teamname) //teamname is set only if teamsay is on
  779.  
  780. for(new i = 0; i < inum; i++) {
  781. owner = botowner[players[i]]
  782. if(owner && alive != is_user_alive(owner)) client_print(owner,print_chat, "%s",text)
  783. }
  784. }
  785.  
  786. bot_command(id,cmd[],arg1[]="",arg2[]="") {
  787. if(strlen(arg2)) engclient_cmd(id,cmd,arg1,arg2)
  788. else if(strlen(arg1)) engclient_cmd(id,cmd,arg1)
  789. else engclient_cmd(id,cmd)
  790. }
  791.  
  792. slotmenu(id,bool:mode) {
  793. hasmenu[id] = mode ? 2 : 0
  794. message_begin(MSG_ONE,gMsg_ShowMenu,{0,0,0},id)
  795. write_short(mode ? slotmenukeys : 0)
  796. write_char(-1)
  797. write_byte(0)
  798. write_string("^n")
  799. message_end()
  800. }
  801.  
  802. bot_addforwards() {
  803. fow_cmdstart = register_forward(FM_CmdStart,"fm_cmdstart",0)
  804. fow_serverframe = register_forward(FM_StartFrame,"fm_serverframe",1)
  805. fow_clientkill = register_forward(FM_ClientKill,"fm_clientkill",0)
  806.  
  807. set_task(1.0,"check_botinfo",TASK_BOTINFO, "",0, "b")
  808. }
  809.  
  810. bot_delforwards() {
  811. unregister_forward(FM_CmdStart,fow_cmdstart,0)
  812. unregister_forward(FM_StartFrame,fow_serverframe,1)
  813. unregister_forward(FM_ClientKill,fow_clientkill,0)
  814.  
  815. remove_task(TASK_BOTINFO)
  816. }
  817.  
  818. bot_settings(id) {
  819. set_user_info(id, "model", "gordon")
  820. set_user_info(id, "rate", "3500")
  821. set_user_info(id, "cl_updaterate", "30")
  822. set_user_info(id, "cl_lw", "0")
  823. set_user_info(id, "cl_lc", "0")
  824. set_user_info(id, "tracker", "0")
  825. set_user_info(id, "cl_dlmax", "128")
  826. set_user_info(id, "lefthand", "1")
  827. set_user_info(id, "friends", "0")
  828. set_user_info(id, "dm", "0")
  829. set_user_info(id, "ah", "1")
  830.  
  831. set_user_info(id, "*bot", "1")
  832. set_user_info(id, "_cl_autowepswitch", "1")
  833. set_user_info(id, "_vgui_menu", "0") //disable vgui so we dont have to
  834. set_user_info(id, "_vgui_menus", "0") //register both 2 types of menus :)
  835. }
  836.  
  837. bot_say(id,team,text[]) {
  838. engclient_cmd(id,team ? "say_team" : "say",text)
  839. handle_saytext(id,text,team)
  840. }
  841.  
  842. reset_controls(owner) {
  843. botmove[owner][0] = 0.0
  844. botmove[owner][1] = 0.0
  845. botmove[owner][2] = 0.0
  846. botangles[owner][0] = 0.0
  847. botangles[owner][1] = 0.0
  848. botangles[owner][2] = 0.0
  849. botbuttons[owner] = 0
  850. botimpulses[owner] = 0
  851. }
  852.