HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. /* Formatright © 2009, ConnorMcLeod
  2.  
  3. c4 management is free software;
  4. you can redistribute it and/or modify it under the terms of the
  5. GNU General Public License as published by the Free Software Foundation.
  6.  
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11.  
  12. You should have received a copy of the GNU General Public License
  13. along with c4 management; if not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17.  
  18. #include <amxmodx>
  19. #include <amxmisc>
  20. #include <fakemeta>
  21. #include <hamsandwich>
  22.  
  23. #define VERSION "0.2.7"
  24.  
  25. #define MAX_PLAYERS 32
  26.  
  27. enum _:BombSites_Datas {
  28. iBsIndex,
  29. szBsModel[5]
  30. }
  31.  
  32. enum _:BombSites_States {
  33. AllSites,
  34. MainSite,
  35. NoSite
  36. }
  37.  
  38. #define StatusIconDontShow 0
  39. #define StatusIconShow 1
  40.  
  41. new const func_bomb_target[] = "func_bomb_target"
  42. new const info_bomb_target[] = "info_bomb_target"
  43.  
  44. new const classname[] = "classname"
  45.  
  46. #define FIND_ENT_BY_CLASSNAME(%1,%2) engfunc(EngFunc_FindEntityByString, %1, classname, %2)
  47.  
  48. #define XTRA_OFS_PLAYER 5
  49. #define m_iTeam 114
  50. #define cs_get_user_team_index(%1) get_pdata_int(%1, m_iTeam, XTRA_OFS_PLAYER)
  51. #define CS_TEAM_CT 2
  52.  
  53. new g_iMaxPlayers
  54.  
  55. new g_pCvarMinCts, g_pCvarMidCts
  56. new g_pCvarStartRoundText, g_pCvarPlanterText
  57.  
  58. new bool:g_bMainSiteSet
  59.  
  60. new szConfigFile[64], g_szMapName[32]
  61. new g_mMainBombSite[BombSites_Datas]
  62. new g_szBombSiteName[16]
  63. new Array:g_aBombSites
  64.  
  65. new Float:g_flCountUntilGameTime
  66. new bool:g_bCountNewSpawns
  67.  
  68. new g_iSyncHud
  69.  
  70. new mp_buytime
  71.  
  72. new gmsgStatusIcon
  73.  
  74. new g_iBombSites_State
  75.  
  76. new g_iC4Carrier
  77.  
  78. public plugin_init()
  79. {
  80. new iEnt, mDatas[BombSites_Datas]
  81. while( (iEnt = FIND_ENT_BY_CLASSNAME(iEnt, func_bomb_target)) )
  82. {
  83. if( g_aBombSites == Invalid_Array )
  84. {
  85. g_aBombSites = ArrayCreate(BombSites_Datas)
  86. }
  87.  
  88. mDatas[iBsIndex] = iEnt
  89. pev(iEnt, pev_model, mDatas[szBsModel], charsmax(mDatas[szBsModel]))
  90. ArrayPushString(g_aBombSites, mDatas)
  91. }
  92. while( (iEnt = FIND_ENT_BY_CLASSNAME(iEnt, info_bomb_target)) )
  93. {
  94. if( g_aBombSites == Invalid_Array )
  95. {
  96. g_aBombSites = ArrayCreate(BombSites_Datas)
  97. }
  98.  
  99. mDatas[iBsIndex] = iEnt
  100. pev(iEnt, pev_model, mDatas[szBsModel], charsmax(mDatas[szBsModel]))
  101. ArrayPushString(g_aBombSites, mDatas)
  102. }
  103.  
  104. if( g_aBombSites == Invalid_Array )
  105. {
  106. register_plugin("c4 management", "NotBombMap", "ConnorMcLeod")
  107. pause("ad")
  108. return
  109. }
  110.  
  111. register_plugin("c4 management", VERSION, "ConnorMcLeod")
  112. register_dictionary("c4management.txt")
  113.  
  114. g_pCvarMinCts = register_cvar("bm_minct", "0")
  115. g_pCvarMidCts = register_cvar("bm_midct", "4")
  116. g_pCvarStartRoundText = register_cvar("bm_roundstart_text", "1")
  117. g_pCvarPlanterText = register_cvar("bm_planter_text", "1")
  118.  
  119. get_mapname(g_szMapName, charsmax(g_szMapName))
  120.  
  121. get_localinfo("amxx_configsdir", szConfigFile, charsmax(szConfigFile))
  122. format(szConfigFile, charsmax(szConfigFile), "%s/bombsites.ini", szConfigFile)
  123. if( !file_exists(szConfigFile) )
  124. {
  125. new iFile = fopen(szConfigFile, "at")
  126. fprintf(iFile, "; c4 management configuration file^n")
  127. fclose(iFile)
  128. }
  129.  
  130. g_iMaxPlayers = get_maxplayers()
  131.  
  132. GetMainBombSiteByFile()
  133.  
  134. register_event("HLTV", "Event_HLTV_New_Round", "a", "1=0", "2=0")
  135. register_logevent("LogEvent_RoundStart", 2, "1=Round_Start")
  136. register_logevent("Logevent_Round_End", 2, "1=Round_End")
  137. RegisterHam(Ham_Spawn, "player", "Player_Spawn_Post", 1)
  138.  
  139. register_event("WeapPickup", "Event_WeapPickup_c4", "be", "1=6")
  140. register_message(get_user_msgid("StatusIcon"), "Message_StatusIcon")
  141.  
  142. register_event("BombDrop", "Event_BombDrop", "bc")
  143.  
  144. register_event("TextMsg", "Event_TextMsg_C4PlantAtBombSpot", "be", "1=4", "2=#C4_Plant_At_Bomb_Spot")
  145.  
  146. register_clcmd("bm_mark_bs", "AdminCommand_MarkBombSite", ADMIN_CFG, " <BombSite Name>")
  147.  
  148. g_iSyncHud = CreateHudSyncObj()
  149. mp_buytime = get_cvar_pointer("mp_buytime")
  150. gmsgStatusIcon = get_user_msgid("StatusIcon")
  151. }
  152.  
  153. GetMainBombSiteByFile()
  154. {
  155. new iFile = fopen(szConfigFile, "rt")
  156. if( iFile )
  157. {
  158. new szData[64], szMapname[32], szModel[5], szBombSiteName[16]
  159. while( fgets(iFile, szData, charsmax(szData)) )
  160. {
  161. if( !szData[0] || szData[0] == '/' || szData[0] == ';' || szData[0] == '#' )
  162. {
  163. continue
  164. }
  165.  
  166. trim(szData)
  167. parse(szData, szMapname, charsmax(szMapname),
  168. szModel, charsmax(szModel),
  169. szBombSiteName, charsmax(szBombSiteName))
  170.  
  171. if( equali(szMapname, g_szMapName) )
  172. {
  173. new iEnt
  174. // less efficient than engine but used only at map start
  175. iEnt = FIND_ENT_BY_MODELNAME(g_iMaxPlayers, func_bomb_target, szModel)
  176.  
  177. if( !iEnt )
  178. {
  179. iEnt = FIND_ENT_BY_MODELNAME(g_iMaxPlayers, info_bomb_target, szModel)
  180. }
  181.  
  182. if( iEnt )
  183. {
  184. g_mMainBombSite[iBsIndex] = iEnt
  185. g_mMainBombSite[szBsModel] = szModel
  186. remove_quotes(szBombSiteName)
  187. g_szBombSiteName = szBombSiteName
  188.  
  189. g_bMainSiteSet = true
  190. }
  191. break
  192. }
  193. }
  194. fclose(iFile)
  195. }
  196. }
  197.  
  198. public plugin_pause()
  199. {
  200. new iBombSiteNum = ArraySize(g_aBombSites)
  201. new mBombSiteDatas[BombSites_Datas]
  202.  
  203. for(new i; i<iBombSiteNum; i++)
  204. {
  205. ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
  206. SetBombSite(mBombSiteDatas[iBsIndex], true)
  207. }
  208. }
  209.  
  210. public plugin_end()
  211. {
  212. if( g_aBombSites != Invalid_Array )
  213. {
  214. ArrayDestroy(g_aBombSites)
  215. }
  216. }
  217.  
  218. public Event_HLTV_New_Round()
  219. {
  220. g_iC4Carrier = 0
  221. g_bCountNewSpawns = false
  222. g_iBombSites_State = AllSites
  223. }
  224.  
  225. public Event_BombDrop()
  226. {
  227. g_iC4Carrier = 0
  228.  
  229. if( read_data(4) ) // Bomb Planted
  230. {
  231. g_bCountNewSpawns = false
  232. }
  233. }
  234.  
  235. public Logevent_Round_End()
  236. {
  237. g_bCountNewSpawns = false
  238. }
  239.  
  240. public LogEvent_RoundStart()
  241. {
  242. g_bCountNewSpawns = true
  243. g_flCountUntilGameTime = get_gametime() + get_pcvar_float(mp_buytime) * 60.0
  244.  
  245. if(!g_bMainSiteSet)
  246. {
  247. return
  248. }
  249.  
  250. CountCounterTerrorists()
  251. }
  252.  
  253. public AdminCommand_MarkBombSite(id, level, cid)
  254. {
  255. if( !cmd_access(id, level, cid, 2) )
  256. {
  257. return PLUGIN_HANDLED
  258. }
  259.  
  260. if(g_bMainSiteSet)
  261. {
  262. client_print(id, print_console, "%L", id, "BM_ALREADY")
  263. client_cmd(id, "spk buttons/latchlocked1")
  264. return PLUGIN_HANDLED
  265. }
  266.  
  267. new iBombSiteNum = ArraySize(g_aBombSites)
  268.  
  269. new mBombSiteDatas[BombSites_Datas], iEnt
  270. new Float:fVecOrigin[3], Float:fVecAbsMin[3], Float:fVecAbsMax[3]
  271.  
  272. for(new i=0; i<iBombSiteNum; i++)
  273. {
  274. ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
  275. iEnt = mBombSiteDatas[iBsIndex]
  276.  
  277. pev(id, pev_origin, fVecOrigin)
  278. pev(iEnt, pev_absmin, fVecAbsMin)
  279. pev(iEnt, pev_absmax, fVecAbsMax)
  280.  
  281. if( (fVecAbsMin[0] <= fVecOrigin[0] <= fVecAbsMax[0])
  282. && (fVecAbsMin[1] <= fVecOrigin[1] <= fVecAbsMax[1])
  283. && (-72.0 <= (((fVecAbsMax[2] + fVecAbsMin[2]) / 2.0) - fVecOrigin[2]) <= 72.0) )
  284. {
  285. read_argv(1, g_szBombSiteName, charsmax(g_szBombSiteName))
  286. new iFile = fopen(szConfigFile, "at")
  287. fprintf(iFile, "^n%s %s ^"%s^"", g_szMapName, mBombSiteDatas[szBsModel], g_szBombSiteName)
  288. fclose(iFile)
  289.  
  290. g_mMainBombSite = mBombSiteDatas
  291. g_bMainSiteSet = true
  292.  
  293. client_print(id, print_console, "%L", id, "BM_DEFINED")
  294. client_cmd(id, "spk events/task_complete")
  295. return PLUGIN_HANDLED
  296. }
  297. }
  298.  
  299. client_print(id, print_console, "%L", id, "BM_NOTBOMBSITE")
  300. client_cmd(id, "spk events/friend_died")
  301. return PLUGIN_HANDLED
  302. }
  303.  
  304. public Event_WeapPickup_c4( id )
  305. {
  306. g_iC4Carrier = id
  307. }
  308.  
  309. public Message_StatusIcon(/*iMsgId, iMsgDest, id*/)
  310. {
  311. if( g_iBombSites_State != AllSites && get_msg_arg_int(1) == StatusIconShow )
  312. {
  313. new szIcon[4]
  314. get_msg_arg_string(2, szIcon, charsmax(szIcon))
  315. if( get_msg_arg_string(2, szIcon, charsmax(szIcon)) == 2 // check "c4" length first
  316. && equal(szIcon, "c4") )
  317. {
  318. switch( g_iBombSites_State )
  319. {
  320. case NoSite:
  321. {
  322. set_msg_arg_int(1, ARG_BYTE, 0)
  323. }
  324. case MainSite:
  325. {
  326. set_msg_arg_int(3, ARG_BYTE, 200)
  327. set_msg_arg_int(4, ARG_BYTE, 100)
  328. }
  329. }
  330. }
  331. }
  332. }
  333.  
  334. public Event_TextMsg_C4PlantAtBombSpot(id)
  335. {
  336. if( !get_pcvar_num(g_pCvarPlanterText) )
  337. {
  338. return
  339. }
  340.  
  341. new iBombSiteNum = ArraySize(g_aBombSites)
  342.  
  343. new mBombSiteDatas[BombSites_Datas], iEnt
  344. new Float:fVecOrigin[3], Float:fVecAbsMin[3], Float:fVecAbsMax[3]
  345.  
  346. for(new i=0; i<iBombSiteNum; i++)
  347. {
  348. ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
  349. iEnt = mBombSiteDatas[iBsIndex]
  350.  
  351. pev(id, pev_origin, fVecOrigin)
  352. pev(iEnt, pev_absmin, fVecAbsMin)
  353. pev(iEnt, pev_absmax, fVecAbsMax)
  354.  
  355. if( (fVecAbsMin[0] <= fVecOrigin[0] <= fVecAbsMax[0])
  356. && (fVecAbsMin[1] <= fVecOrigin[1] <= fVecAbsMax[1])
  357. && (-72.0 <= (((fVecAbsMax[2] + fVecAbsMin[2]) / 2.0) - fVecOrigin[2]) <= 72.0) )
  358. {
  359. switch( g_iBombSites_State )
  360. {
  361. case NoSite:
  362. {
  363. client_print(id, print_center, "%L", id, "BM_AD_NOPLANT", get_pcvar_num(g_pCvarMinCts))
  364. }
  365. case MainSite:
  366. {
  367. client_print(id, print_center, "%L", id, "BM_AD_ONLYMAIN",
  368. get_pcvar_num(g_pCvarMidCts), g_szBombSiteName)
  369. }
  370. }
  371.  
  372. break
  373. }
  374. }
  375. }
  376.  
  377. public Player_Spawn_Post(id)
  378. {
  379. if( g_bMainSiteSet
  380. && g_bCountNewSpawns
  381. && is_user_alive(id)
  382. && cs_get_user_team_index(id) == CS_TEAM_CT )
  383. {
  384. if( g_flCountUntilGameTime < get_gametime() )
  385. {
  386. g_bCountNewSpawns = false
  387. return
  388. }
  389. CountCounterTerrorists()
  390. }
  391. }
  392.  
  393. CountCounterTerrorists()
  394. {
  395. new iPlayers[MAX_PLAYERS], iNum, iCtNum
  396. get_players(iPlayers, iNum, "h")
  397.  
  398. for(new i; i<iNum; i++)
  399. {
  400. if( cs_get_user_team_index(iPlayers[i]) == CS_TEAM_CT )
  401. {
  402. iCtNum++
  403. }
  404. }
  405.  
  406. new iMinCts = get_pcvar_num(g_pCvarMinCts)
  407. new iMidCts = get_pcvar_num(g_pCvarMidCts)
  408.  
  409. new const szTag[] = "C4 Management"
  410.  
  411. new iBombSiteNum = ArraySize(g_aBombSites)
  412. new mBombSiteDatas[BombSites_Datas]
  413.  
  414. if( iCtNum < iMinCts)
  415. {
  416. switch( get_pcvar_num(g_pCvarStartRoundText) )
  417. {
  418. case 1:
  419. {
  420. client_print(0, print_chat, "* [%s] %L", szTag, LANG_PLAYER, "BM_AD_NOPLANT", iMinCts)
  421. }
  422. case 2:
  423. {
  424. set_hudmessage(200, 50, 50, -1.0, 0.15, .holdtime=8.0, .channel=-1)
  425. ShowSyncHudMsg(0, g_iSyncHud, "%s : %L", szTag, LANG_PLAYER, "BM_AD_NOPLANT", iMinCts)
  426. }
  427. }
  428.  
  429. for(new i; i<iBombSiteNum; i++)
  430. {
  431. ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
  432. SetBombSite(mBombSiteDatas[iBsIndex], false)
  433. }
  434.  
  435. g_iBombSites_State = NoSite
  436. if( g_iC4Carrier )
  437. {
  438. Send_StatusIcon_c4(g_iC4Carrier)
  439. }
  440. }
  441. else if( iCtNum < iMidCts)
  442. {
  443. switch( get_pcvar_num(g_pCvarStartRoundText) )
  444. {
  445. case 1:
  446. {
  447. client_print(0, print_chat, "* [%s] %L", szTag, LANG_PLAYER, "BM_AD_ONLYMAIN", iMidCts, g_szBombSiteName)
  448. }
  449. case 2:
  450. {
  451. set_hudmessage(200, 100, 0, -1.0, 0.15, .holdtime=8.0, .channel=-1)
  452. ShowSyncHudMsg(0, g_iSyncHud, "%s : %L", szTag, LANG_PLAYER, "BM_AD_ONLYMAIN", iMidCts, g_szBombSiteName)
  453. }
  454. }
  455.  
  456. new iEnt
  457. for(new i; i<iBombSiteNum; i++)
  458. {
  459. ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
  460. iEnt = mBombSiteDatas[iBsIndex]
  461. SetBombSite(iEnt, iEnt == g_mMainBombSite[iBsIndex] ? true : false)
  462. }
  463.  
  464. g_iBombSites_State = MainSite
  465. if( g_iC4Carrier )
  466. {
  467. Send_StatusIcon_c4(g_iC4Carrier, StatusIconShow, 200, 100, 0)
  468. }
  469. }
  470. else
  471. {
  472. switch( get_pcvar_num(g_pCvarStartRoundText) )
  473. {
  474. case 1:
  475. {
  476. client_print(0, print_chat, "* [%s] %L", szTag, LANG_PLAYER, "BM_AD_ALLSITES")
  477. }
  478. case 2:
  479. {
  480. set_hudmessage(50, 200, 50, -1.0, 0.15, .holdtime=8.0, .channel=-1)
  481. ShowSyncHudMsg(0, g_iSyncHud, "%s : %L", szTag, LANG_PLAYER, "BM_AD_ALLSITES")
  482. }
  483. }
  484.  
  485. for(new i; i<iBombSiteNum; i++)
  486. {
  487. ArrayGetArray(g_aBombSites, i, mBombSiteDatas)
  488. SetBombSite(mBombSiteDatas[iBsIndex], true)
  489. }
  490.  
  491. g_iBombSites_State = AllSites
  492. if( g_iC4Carrier )
  493. {
  494. Send_StatusIcon_c4(g_iC4Carrier, StatusIconShow, 0, 160, 0)
  495. }
  496. }
  497. }
  498.  
  499. SetBombSite(iEnt, bool:bActive)
  500. {
  501. set_pev(iEnt, pev_solid, bActive ? SOLID_TRIGGER : SOLID_NOT)
  502. }
  503.  
  504. Send_StatusIcon_c4(id, Mode=StatusIconDontShow, r=0, g=0, b=0)
  505. {
  506. message_begin(MSG_ONE_UNRELIABLE, gmsgStatusIcon, .player=id)
  507. write_byte(Mode)
  508. write_string("c4")
  509. if( Mode )
  510. {
  511. write_byte(r)
  512. write_byte(g)
  513. write_byte(b)
  514. }
  515. message_end()
  516. }
  517.  
  518. FIND_ENT_BY_MODELNAME(const iStartEnt, const szClassName[], const szModel[])
  519. {
  520. new iEnt = iStartEnt
  521. new szMdl[72]
  522. while( (iEnt = FIND_ENT_BY_CLASSNAME(iEnt, szClassName)) )
  523. {
  524. pev(iEnt, pev_model, szMdl, charsmax(szMdl))
  525. if( equal(szMdl, szModel) )
  526. {
  527. return iEnt
  528. }
  529. }
  530. return 0
  531. }