HLMOD.HU Forrás Megtekintés - www.hlmod.hu
  1. #include <amxmodx>
  2. #include <engine>
  3. #include <fakemeta>
  4. #include <hamsandwich>
  5.  
  6. #define PLUGIN "Weapon Skin System"
  7. #define VERSION "0.6.0-50"
  8. #define AUTHOR "Mistrick"
  9.  
  10. #pragma semicolon 1
  11.  
  12. #define DEFAULT_SKIN_MENU
  13.  
  14. #define MODEL_NOT_SET 0
  15.  
  16. #define is_valid_pev(%0) (pev_valid(%0) == 2)
  17. #define get_weapon_skin(%0) pev(%0, pev_iuser4)
  18. #define set_weapon_skin(%0,%1) set_pev(%0, pev_iuser4, %1)
  19.  
  20. const XO_CBASEPLAYER = 5;
  21. const XO_CBASEPLAYERWEAPON = 4;
  22.  
  23. const m_pPlayer = 41;
  24. const m_pNext = 42;
  25. const m_iId = 43;
  26. const m_pActiveItem = 373;
  27. const m_rgpPlayerItems_CWeaponBox = 34;
  28. const m_rgpPlayerItems_CBasePlayer = 367;
  29.  
  30. enum Forwards
  31. {
  32. WEAPON_DEPLOY,
  33. WEAPON_HOLSTER,
  34. WEAPON_CAN_PICKUP,
  35. WEAPON_DROP,
  36. WEAPON_ADD_TO_PLAYER
  37. };
  38.  
  39. enum
  40. {
  41. ADD_BY_WEAPONBOX,
  42. ADD_BY_ARMORY_ENTITY,
  43. ADD_BY_BUYZONE
  44. };
  45.  
  46. enum
  47. {
  48. WEAPON_MODEL_IGNORED,
  49. WEAPON_MODEL_CHANGED
  50. };
  51.  
  52. new g_iForwards[Forwards];
  53. new Float:g_flLastTouchTime;
  54. new bool:g_bIgnoreSetModel = true;
  55.  
  56. enum _:SkinInfo
  57. {
  58. WeaponID,
  59. SkinName[32],
  60. ModelV,
  61. ModelP,
  62. ModelW[64]
  63. };
  64.  
  65. new const FILE_MODELS[] = "weapon_skins.ini";
  66.  
  67. new Array:g_aWeaponSkins;
  68. new g_LoadedWeapons;
  69. new g_iWeaponSkinsCount;
  70. new g_iPlayerSkins[33][32];
  71.  
  72. public plugin_init()
  73. {
  74. register_plugin(PLUGIN, VERSION, AUTHOR);
  75.  
  76. #if defined DEFAULT_SKIN_MENU
  77. register_impulse(201, "Command_ChangeSkin");
  78. register_clcmd("say /skins", "Command_ChangeSkin");
  79. register_clcmd("say /skinreset", "Command_ResetSkin");
  80. #endif // DEFAULT_SKIN_MENU
  81.  
  82. // forward cs_weapon_deploy(id, weapon, weaponid, skin);
  83. g_iForwards[WEAPON_DEPLOY] = CreateMultiForward("wss_weapon_deploy", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL);
  84.  
  85. // forward cs_weapon_holster(id, weapon, weaponid, skin);
  86. g_iForwards[WEAPON_HOLSTER] = CreateMultiForward("wss_weapon_holster", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL, FP_CELL);
  87.  
  88. // forward cs_weapon_can_pickup(id, weaponbox, weapon, weaponid, skin);
  89. // should return 1 for block pickup
  90. g_iForwards[WEAPON_CAN_PICKUP] = CreateMultiForward("wss_weapon_can_pickup", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL);
  91.  
  92. // forward cs_weapon_drop(id, weaponbox, weapon, weaponid, skin);
  93. g_iForwards[WEAPON_DROP] = CreateMultiForward("wss_weapon_drop", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_CELL);
  94.  
  95. RegisterWeapons();
  96. RegisterWeaponDrop();
  97. }
  98.  
  99. RegisterWeapons()
  100. {
  101. for(new i = CSW_P228, weapon_name[32]; i < CSW_P90; i++)
  102. {
  103. if(get_weaponname(i, weapon_name, charsmax(weapon_name)))
  104. {
  105. RegisterHam(Ham_Item_Deploy, weapon_name, "Ham_WeaponDeploy_Post", .Post = true);
  106. RegisterHam(Ham_Item_Holster, weapon_name, "Ham_WeaponHolster_Post", .Post = true);
  107. RegisterHam(Ham_Item_AddToPlayer, weapon_name, "Ham_WeaponAddToPlayer_Post", .Post = true);
  108. }
  109. }
  110. register_touch("armoury_entity", "player", "CArmouryEntity__Touch");
  111. register_touch("weaponbox", "player", "CWeaponBox__Touch");
  112. }
  113. RegisterWeaponDrop()
  114. {
  115. RegisterHam(Ham_Spawn, "grenade", "Ham_WeaponSpawn_Post", .Post = true);
  116. RegisterHam(Ham_Spawn, "weaponbox", "Ham_WeaponSpawn_Post", .Post = true);
  117. register_forward(FM_SetModel, "FM_SetModel_Pre", ._post = false);
  118. }
  119.  
  120. public plugin_precache()
  121. {
  122. new file_path[128]; get_localinfo("amxx_configsdir", file_path, charsmax(file_path));
  123. format(file_path, charsmax(file_path), "%s/%s", file_path, FILE_MODELS);
  124.  
  125. new file = fopen(file_path, "rt");
  126.  
  127. if(!file)
  128. {
  129. set_fail_state("File not found!");
  130. }
  131.  
  132. g_aWeaponSkins = ArrayCreate(SkinInfo, 1);
  133.  
  134. // forward wss_loaded_skin(index, weaponid, name[]);
  135. new fwd = CreateMultiForward("wss_loaded_skin", ET_IGNORE, FP_CELL, FP_CELL, FP_STRING);
  136.  
  137. new buffer[256], weapon_name[32], skin_name[32], model_v[64], model_p[64], model_w[64];
  138. new weaponid, skin_info[SkinInfo];
  139. new ret;
  140.  
  141. while(!feof(file))
  142. {
  143. fgets(file, buffer, charsmax(buffer));
  144.  
  145. if(!buffer[0] || buffer[0] == ';') continue;
  146.  
  147. parse(buffer, weapon_name, charsmax(weapon_name), skin_name, charsmax(skin_name), model_v, charsmax(model_v), model_p, charsmax(model_p), model_w, charsmax(model_w));
  148. weaponid = get_weapon_csw(weapon_name);
  149.  
  150. if(!weaponid) continue;
  151.  
  152. skin_info[WeaponID] = weaponid;
  153.  
  154. g_LoadedWeapons |= (1 << weaponid);
  155.  
  156. if(model_v[0] && file_exists(model_v))
  157. {
  158. skin_info[ModelV] = engfunc(EngFunc_AllocString, model_v);
  159. precache_model(model_v);
  160. }
  161. if(model_p[0] && file_exists(model_p))
  162. {
  163. skin_info[ModelP] = engfunc(EngFunc_AllocString, model_p);
  164. precache_model(model_p);
  165. }
  166. if(model_w[0] && file_exists(model_w))
  167. {
  168. copy(skin_info[ModelW], charsmax(skin_info[ModelW]), model_w);
  169. precache_model(model_w);
  170. }
  171. copy(skin_info[SkinName], charsmax(skin_info[SkinName]), skin_name);
  172.  
  173. ExecuteForward(fwd, ret, g_iWeaponSkinsCount + 1, weaponid, skin_name);
  174.  
  175. ArrayPushArray(g_aWeaponSkins, skin_info);
  176. g_iWeaponSkinsCount++;
  177.  
  178. skin_info[ModelV] = MODEL_NOT_SET; skin_info[ModelP] = MODEL_NOT_SET; skin_info[ModelW] = MODEL_NOT_SET;
  179. }
  180.  
  181. fclose(file);
  182.  
  183. if(!g_iWeaponSkinsCount)
  184. {
  185. ArrayDestroy(g_aWeaponSkins);
  186. set_fail_state("File is empty!");
  187. }
  188. }
  189.  
  190. public plugin_natives()
  191. {
  192. register_library("weapon_skin_system");
  193. register_native("wss_get_weapon_skin_index", "native_get_weapon_skin_index");
  194. register_native("wss_get_skin_name", "native_get_skin_name");
  195. register_native("wss_set_user_skin", "native_set_user_skin");
  196. }
  197.  
  198. // native wss_get_weapon_skin_index(weapon);
  199. public native_get_weapon_skin_index(plugin, params)
  200. {
  201. enum { arg_weapon = 1 };
  202.  
  203. new weapon = get_param(arg_weapon);
  204.  
  205. return get_weapon_skin(weapon);
  206. }
  207.  
  208. // native wss_get_skin_name(skin, name[], len);
  209. public native_get_skin_name(plugin, params)
  210. {
  211. enum
  212. {
  213. arg_skin = 1,
  214. arg_name,
  215. arg_len
  216. };
  217.  
  218. new skin = get_param(arg_skin);
  219.  
  220. if(skin < 1 || skin > g_iWeaponSkinsCount)
  221. {
  222. log_error(AMX_ERR_NATIVE, "[WSS] Get skin name: wrong skin index! index %d", skin);
  223. return 0;
  224. }
  225.  
  226. new skin_info[SkinInfo];
  227. ArrayGetArray(g_aWeaponSkins, skin - 1, skin_info);
  228. set_string(arg_name, skin_info[SkinName], get_param(arg_len));
  229.  
  230. return 1;
  231. }
  232.  
  233. // native wss_set_user_skin(id, weaponid, skin_index);
  234. public native_set_user_skin(plugin, params)
  235. {
  236. enum
  237. {
  238. arg_id = 1,
  239. arg_weaponid,
  240. arg_skin_index
  241. };
  242.  
  243. new id = get_param(arg_id);
  244. new weaponid = get_param(arg_weaponid);
  245. new skin_index = get_param(arg_skin_index);
  246.  
  247. if(id < 1 || id > 32)
  248. {
  249. log_error(AMX_ERR_NATIVE, "[WSS] Set user skin: wrong player index! index %d", id);
  250. return 0;
  251. }
  252.  
  253. if(!weaponid)
  254. {
  255. arrayset(g_iPlayerSkins[id], 0, sizeof(g_iPlayerSkins[]));
  256. return 1;
  257. }
  258.  
  259. g_iPlayerSkins[id][weaponid] = skin_index;
  260.  
  261. return 1;
  262. }
  263.  
  264. public client_connect(id)
  265. {
  266. arrayset(g_iPlayerSkins[id], 0, sizeof(g_iPlayerSkins[]));
  267. }
  268.  
  269. #if defined DEFAULT_SKIN_MENU
  270. public Command_ChangeSkin(id)
  271. {
  272. new menu = menu_create("\w~\rSkin Választás\w~ \y", "SkinMenu_Handler");
  273.  
  274. new skin_info[SkinInfo];
  275. for(new i; i < g_iWeaponSkinsCount; i++)
  276. {
  277. ArrayGetArray(g_aWeaponSkins, i, skin_info);
  278. menu_additem(menu, skin_info[SkinName]);
  279. }
  280. menu_setprop(menu, MPROP_BACKNAME, "\yVissza");
  281. menu_setprop(menu, MPROP_NEXTNAME, "\yTovább");
  282. menu_setprop(menu, MPROP_EXITNAME, "\yKilépés");
  283. menu_display(id, menu);
  284. }
  285. public SkinMenu_Handler(id, menu, item)
  286. {
  287. if(item == MENU_EXIT)
  288. {
  289. menu_destroy(menu);
  290. return PLUGIN_HANDLED;
  291. }
  292.  
  293. new skin_info[SkinInfo];
  294. ArrayGetArray(g_aWeaponSkins, item, skin_info);
  295.  
  296. g_iPlayerSkins[id][skin_info[WeaponID]] = item + 1;
  297.  
  298. new weapon, weaponid;
  299. new cur_weapon = get_pdata_cbase(id, m_pActiveItem, XO_CBASEPLAYER);
  300.  
  301. #define MAX_ITEM_SLOTS 6
  302.  
  303. for(new i; i < MAX_ITEM_SLOTS; i++)
  304. {
  305. weapon = get_pdata_cbase(id, m_rgpPlayerItems_CBasePlayer + i, XO_CBASEPLAYER);
  306.  
  307. while (is_valid_pev(weapon))
  308. {
  309. weaponid = get_pdata_int(weapon, m_iId, XO_CBASEPLAYERWEAPON);
  310.  
  311. if(weaponid == skin_info[WeaponID])
  312. {
  313. set_weapon_skin(weapon, item + 1);
  314.  
  315. if(weapon == cur_weapon)
  316. {
  317. if(skin_info[ModelV]) set_pev(id, pev_viewmodel, skin_info[ModelV]);
  318. if(skin_info[ModelP]) set_pev(id, pev_weaponmodel, skin_info[ModelP]);
  319. }
  320. // stop cycles
  321. i = MAX_ITEM_SLOTS; break;
  322. }
  323.  
  324. weapon = get_pdata_cbase(weapon, m_pNext, XO_CBASEPLAYERWEAPON);
  325. }
  326. }
  327.  
  328. menu_destroy(menu);
  329. return PLUGIN_HANDLED;
  330. }
  331.  
  332. public Command_ResetSkin(id)
  333. {
  334. static weapons[][] =
  335. {
  336. "", "weapon_p228", "weapon_shield", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4",
  337. "weapon_mac10", "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45",
  338. "weapon_sg550", "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy",
  339. "weapon_m249", "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle",
  340. "weapon_sg552", "weapon_ak47", "weapon_knife", "weapon_p90"
  341. };
  342.  
  343. new menu = menu_create("Skin Reset", "SkinReset_Handler");
  344.  
  345. for(new i = 1, num[2]; i < 32; i++)
  346. {
  347. if(g_LoadedWeapons & (1 << i) && g_iPlayerSkins[id][i])
  348. {
  349. num[0] = i;
  350. menu_additem(menu, weapons[i], num);
  351. }
  352. }
  353.  
  354. menu_display(id, menu);
  355. }
  356.  
  357. public SkinReset_Handler(id, menu, item)
  358. {
  359. if(item == MENU_EXIT)
  360. {
  361. menu_destroy(menu);
  362. return PLUGIN_HANDLED;
  363. }
  364.  
  365. new info[2], buffer;
  366. menu_item_getinfo(menu, item, buffer, info, charsmax(info), .callback = buffer);
  367.  
  368. new weaponid = info[0];
  369.  
  370. g_iPlayerSkins[id][weaponid] = 0;
  371.  
  372. menu_destroy(menu);
  373. return PLUGIN_HANDLED;
  374. }
  375. #endif // DEFAULT_SKIN_MENU
  376.  
  377. public Ham_WeaponDeploy_Post(const weapon)
  378. {
  379. new id = get_pdata_cbase(weapon, m_pPlayer, XO_CBASEPLAYERWEAPON);
  380. new weaponid = get_pdata_int(weapon, m_iId, XO_CBASEPLAYERWEAPON);
  381.  
  382. #if defined _DEBUG
  383. client_print(0, print_chat, "deploy: id %d, weapon %d, weaponid %d", id, weapon, weaponid);
  384. #endif // _DEBUG
  385.  
  386. new skin = get_weapon_skin(weapon);
  387. if(skin)
  388. {
  389. new skin_info[SkinInfo];
  390. ArrayGetArray(g_aWeaponSkins, skin - 1, skin_info);
  391. if(skin_info[ModelV]) set_pev(id, pev_viewmodel, skin_info[ModelV]);
  392. if(skin_info[ModelP]) set_pev(id, pev_weaponmodel, skin_info[ModelP]);
  393.  
  394. new ret; ExecuteForward(g_iForwards[WEAPON_DEPLOY], ret, id, weapon, weaponid, skin);
  395. }
  396. }
  397.  
  398. public Ham_WeaponHolster_Post(const weapon)
  399. {
  400. new id = get_pdata_cbase(weapon, m_pPlayer, XO_CBASEPLAYERWEAPON);
  401. new weaponid = get_pdata_int(weapon, m_iId, XO_CBASEPLAYERWEAPON);
  402.  
  403. #if defined _DEBUG
  404. client_print(0, print_chat, "holster: id %d, weapon %d, weaponid %d", id, weapon, weaponid);
  405. #endif // _DEBUG
  406.  
  407. new skin = get_weapon_skin(weapon);
  408. if(skin)
  409. {
  410. new ret; ExecuteForward(g_iForwards[WEAPON_HOLSTER], ret, id, weapon, weaponid, skin);
  411. }
  412. }
  413.  
  414. public CArmouryEntity__Touch(ent, id)
  415. {
  416. g_flLastTouchTime = get_gametime();
  417. }
  418.  
  419. public CWeaponBox__Touch(ent, id)
  420. {
  421. #define MAX_ITEM_TYPES 6
  422.  
  423. for(new i, weapon; i < MAX_ITEM_TYPES; i++)
  424. {
  425. weapon = get_pdata_cbase(ent, m_rgpPlayerItems_CWeaponBox + i, XO_CBASEPLAYERWEAPON);
  426.  
  427. if(is_valid_pev(weapon))
  428. {
  429. new id = pev(ent, pev_owner);
  430. new weaponid = get_pdata_int(weapon, m_iId, XO_CBASEPLAYERWEAPON);
  431.  
  432. new skin = get_weapon_skin(weapon);
  433. if(skin)
  434. {
  435. #if defined _DEBUG
  436. client_print(0, print_chat, "can pickup: id %d, weaponbox %d, weapon %d, weaponid %d", id, ent, weapon, weaponid);
  437. #endif // _DEBUG
  438.  
  439. new ret; ExecuteForward(g_iForwards[WEAPON_CAN_PICKUP], ret, id, ent, weapon, weaponid, skin);
  440.  
  441. if(ret)
  442. {
  443. return PLUGIN_HANDLED;
  444. }
  445. }
  446. }
  447. }
  448.  
  449. return PLUGIN_CONTINUE;
  450. }
  451.  
  452. public Ham_WeaponAddToPlayer_Post(const weapon, const id)
  453. {
  454. new weaponid = get_pdata_int(weapon, m_iId, XO_CBASEPLAYERWEAPON);
  455.  
  456. #if defined _DEBUG
  457. client_print(0, print_chat, "add_to_player: id %d, weapon %d, weaponid %d", id, weapon, weaponid);
  458. #endif // _DEBUG
  459.  
  460. new type;
  461.  
  462. if (pev(weapon, pev_owner) > 0)
  463. {
  464. type = ADD_BY_WEAPONBOX;
  465. }
  466. else if(get_gametime() == g_flLastTouchTime)
  467. {
  468. type = ADD_BY_ARMORY_ENTITY;
  469. }
  470. else
  471. {
  472. type = ADD_BY_BUYZONE;
  473. }
  474.  
  475. if(type == ADD_BY_ARMORY_ENTITY || type == ADD_BY_WEAPONBOX)
  476. {
  477. return HAM_IGNORED;
  478. }
  479.  
  480. if(get_weapon_skin(weapon))
  481. {
  482. return HAM_IGNORED;
  483. }
  484.  
  485. if(g_iPlayerSkins[id][weaponid])
  486. {
  487. set_weapon_skin(weapon, g_iPlayerSkins[id][weaponid]);
  488. }
  489.  
  490. return HAM_IGNORED;
  491. }
  492.  
  493. public Ham_WeaponSpawn_Post(const ent)
  494. {
  495. if (is_valid_pev(ent))
  496. {
  497. g_bIgnoreSetModel = false;
  498. }
  499. }
  500. public FM_SetModel_Pre(const ent)
  501. {
  502. if(g_bIgnoreSetModel || !is_valid_pev(ent)) return FMRES_IGNORED;
  503.  
  504. g_bIgnoreSetModel = true;
  505.  
  506. new classname[32]; pev(ent, pev_classname, classname, charsmax(classname));
  507. if(equal(classname, "grenade"))
  508. {
  509. new id = pev(ent, pev_owner);
  510. new weaponid = fm_cs_get_grenade_type(ent);
  511.  
  512. #if defined _DEBUG
  513. client_print(0, print_chat, "throw grenade: id %d, weapon %d, weaponid %d", id, ent, weaponid);
  514. #endif // _DEBUG
  515.  
  516. new ret = cs_weapon_drop(id, ent, ent, weaponid);
  517.  
  518. if(ret)
  519. {
  520. return FMRES_SUPERCEDE;
  521. }
  522.  
  523. return FMRES_IGNORED;
  524. }
  525.  
  526. #define MAX_ITEM_TYPES 6
  527.  
  528. for(new i, weapon; i < MAX_ITEM_TYPES; i++)
  529. {
  530. weapon = get_pdata_cbase(ent, m_rgpPlayerItems_CWeaponBox + i, XO_CBASEPLAYERWEAPON);
  531.  
  532. if(is_valid_pev(weapon))
  533. {
  534. new id = pev(ent, pev_owner);
  535. new weaponid = get_pdata_int(weapon, m_iId, XO_CBASEPLAYERWEAPON);
  536.  
  537. #if defined _DEBUG
  538. client_print(0, print_chat, "drop: id %d, weaponbox %d, weapon %d, weaponid %d", id, ent, weapon, weaponid);
  539. #endif // _DEBUG
  540.  
  541. new ret = cs_weapon_drop(id, ent, weapon, weaponid);
  542.  
  543. if(ret)
  544. {
  545. return FMRES_SUPERCEDE;
  546. }
  547. }
  548. }
  549.  
  550. return FMRES_IGNORED;
  551. }
  552.  
  553. cs_weapon_drop(id, weaponbox, weapon, weaponid)
  554. {
  555. new skin = get_weapon_skin(weapon);
  556. if(skin)
  557. {
  558. new skin_info[SkinInfo];
  559. ArrayGetArray(g_aWeaponSkins, skin - 1, skin_info);
  560. engfunc(EngFunc_SetModel, weaponbox, skin_info[ModelW]);
  561.  
  562. new ret; ExecuteForward(g_iForwards[WEAPON_DROP], ret, id, weaponbox, weapon, weaponid, skin);
  563.  
  564. return WEAPON_MODEL_CHANGED;
  565. }
  566. return WEAPON_MODEL_IGNORED;
  567. }
  568.  
  569. stock get_weapon_csw(weapon_name[])
  570. {
  571. static weapons[][] =
  572. {
  573. "", "weapon_p228", "weapon_shield", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4",
  574. "weapon_mac10", "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45",
  575. "weapon_sg550", "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy",
  576. "weapon_m249", "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle",
  577. "weapon_sg552", "weapon_ak47", "weapon_knife", "weapon_p90"
  578. };
  579.  
  580. for(new i = 1; i < sizeof(weapons); i++)
  581. {
  582. if(equali(weapon_name, weapons[i]))
  583. {
  584. return i;
  585. }
  586. }
  587.  
  588. return 0;
  589. }
  590.  
  591. // work only for "grenade" classname
  592. stock fm_cs_get_grenade_type(index)
  593. {
  594. const m_iTeam = 114;
  595. new bits = get_pdata_int(index, m_iTeam);
  596.  
  597. if (bits & (1 << 0))
  598. return CSW_HEGRENADE;
  599. else if (bits & (1 << 1))
  600. return CSW_SMOKEGRENADE;
  601. else if (!bits)
  602. return CSW_FLASHBANG;
  603.  
  604. return 0;
  605. }
  606.