Русское сообщество по скриптингу

Изучение модуля Hamsandwich с нуля [12.08.2013]

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Retro-kolt Lincoln » 11 авг 2013, 17:50

Название статьи: Изучение модуля Hamsandwich с нуля.
Автор: Freedo.m
Источник: amx-x.ru

Предисловие:
Здравствуйте дорогие друзья, сегодня я хочу Вам рассказать о таком замечательном модуле как hamsandwich, с помощью данного модуля можно отлавливать и вызывать большое количество различных событий в игре (forward'ов). Например: получение урона, смерть игрока, спавн игрока, соприкосновение энтити, все эти события и многие другие можно отловить и изменить с помощью модуля hamsandwich, давайте же приступим к делу.

1. Регистрация событий.
[spoiler]Чтобы поймать за хвост то или иное событие, его нужно сначала зарегистрировать.
[pawn]
  1. RegisterHam(A, B, C, D);
[/pawn]
A - Событие которое необходимо отловить.
B - Объект который мы отлавливаем.
C - Название функции в которую мы будем передавать отловленные параметры.
D - Когда событие будет отловлено, до того как оно произошло или после(Pre, Post).

Пример:
[pawn]
  1. #include <amxmodx>

  2. #include <hamsandwich>

  3.  

  4. public plugin_init()

  5. {

  6.         RegisterHam(Ham_Spawn, "player", "Ham_PlayerSpawn_Post", 1);

  7. }

  8.  

  9. public Ham_PlayerSpawn_Post(pPlayer)

  10. {

  11.         // Ваш код

  12. }
[/pawn]
С помощью данного примера мы отловили событие спавна игрока.
Ham_Spawn - Событие спавна.
player - Отлавливаемый объект (тут может быть не только игрок, например какое нибудь оружие).
Ham_PlayerSpawn_Post - Название функции в которую мы передаём необходимые параметры(название может быть любое, но лучше пишите так, чтобы потом сами поняли что это).
1 - Отлавливаем событие после того как оно произошло, что же это значит? Приведу другой пример, мы отлавливаем урон нанесённый игроку, если мы будем отлавливать событие до(то есть 0) его можно будет изменить, так как игрок ещё не получил урона, а вот если мы будем отлавливать событие после(то есть 1), мы уже не сможем его изменить, так как игрок уже получил урон.[/spoiler]
2. Изменение параметров отловленных событий.
[spoiler]Научились ловить события? Хорошо, теперь приступим к их изменениям.
[pawn]
  1. SetHamParamInteger(A, B); // целое значение

  2. SetHamParamFloat(A, B); // дробное значение

  3. SetHamParamString(A, B); // строка (значение содержит символы)

  4. SetHamParamVector(A, B); // дробный массив с векторами в трёх плоскостях (x,y,z)

  5. SetHamParamEntity(A, B); // индекс энтити

  6. SetHamParamTraceResult(A, B); // результат трассировки
[/pawn]
A - Номер параметра который необходимо изменить.
B - Любое значение или строка(зависит от того какой функцией пользуетесь).

Примеры:
[pawn]
  1. #include <amxmodx>

  2. #include <hamsandwich>

  3.  

  4. public plugin_init()

  5. {

  6.         RegisterHam(Ham_Killed, "player", "Ham_PlayerKilled_Pre", 0);

  7. }

  8.  

  9. public Ham_PlayerKilled_Pre(pVictim, pKiller, iCorpse)

  10. {

  11.         SetHamParamInteger(3, 2);

  12. }
[/pawn]
Данный пример изменит параметр iCorpse который отвечает за эффект смерти игрока, теперь все игроки при смерти будут разрываться на куски :D

[pawn]
  1. #include <amxmodx>

  2. #include <hamsandwich>

  3.  

  4. public plugin_init()

  5. {

  6.         RegisterHam(Ham_TakeDamage, "player", "Ham_PlayerTakeDamage_Pre", 0);

  7. }

  8.  

  9. public Ham_PlayerTakeDamage_Pre(pVictim, pInflictor, pAttacker, Float:fDamage, iDamageType)

  10. {

  11.         SetHamParamFloat(4, 100.0);

  12. }
[/pawn]
Изменяем значение fDamage, оно отвечает за количество нанесённого урона, теперь какой бы урон не получил игрок, он всегда будет ровняться 100 (то есть смерть, кэп да?).

[pawn]
  1. #include <amxmodx>

  2. #include <hamsandwich>

  3.  

  4. public plugin_init()

  5. {

  6.         RegisterHam(Ham_GiveAmmo, "player", "Ham_PlayerGiveAmmo_Pre", 0);

  7. }

  8.  

  9. public Ham_PlayerGiveAmmo_Pre(pPlayer, iAmmoAmount, const szAmmoName[], iAmmoMax)

  10. {

  11.         SetHamParamString(3, "338magnum");

  12. }
[/pawn]
Странный плагин... С помощью него ловится событие покупки патронов и какие бы Вы патроны не покупали, купятся патроны 338magnum...

[pawn]
  1. #include <amxmodx>

  2. #include <hamsandwich>

  3.  

  4. public plugin_init()

  5. {

  6.         RegisterHam(Ham_TraceAttack, "player", "Ham_PlayerTraceAttack_Pre", 0);

  7. }

  8.  

  9. public Ham_PlayerTraceAttack_Pre(pVictim, pAttacker, Float:fDamage, Float:fDirection[3], pTr, iDamageType)

  10. {

  11.         fDirection[2] -= 20.0;

  12.         SetHamParamVector(4, fDirection);

  13. }
[/pawn]
Плагин изменяет направление летящей пули, сдвигает её на 20 юнитов вниз.

[pawn]
  1. #include <amxmodx>

  2. #include <hamsandwich>

  3.  

  4. public plugin_init()

  5. {

  6.         RegisterHam(Ham_TraceAttack, "player", "Ham_PlayerTraceAttack_Pre", 0);

  7. }

  8.  

  9. public Ham_PlayerTraceAttack_Pre(pVictim, pAttacker, Float:fDamage, Float:fDirection[3], pTr, iDamageType)

  10. {

  11.         SetHamParamEntity(1, pAttacker);

  12.         SetHamParamEntity(2, pVictim);

  13. }
[/pawn]
Шуточный плагин, с помощью SetHamParamEntity мы изменяем индексы игроков таким образом, что нападающий становится жертвой :-D

[pawn]
  1. #include <amxmodx>

  2. #include <fakemeta>

  3. #include <hamsandwich>

  4.  

  5. public plugin_init()

  6. {

  7.         RegisterHam(Ham_TraceAttack, "player", "Ham_PlayerTraceAttack_Pre", 0);

  8. }

  9.  

  10. public Ham_PlayerTraceAttack_Pre(pVictim, pAttacker, Float:fDamage, Float:fDirection[3], pTr, iDamageType)

  11. {

  12.         set_tr2(pTr, TR_iHitgroup, HIT_HEAD);

  13.         SetHamParamTraceResult(5, pTr);

  14. }
[/pawn]
Тут пришлось подключить модуль fakemeta для того чтобы изменить трассировку атаки, а затем её выставить. Теперь в какую бы часть тела не стреляли, пули всё равно будут попадать в голову.[/spoiler]
Продолжение следует... Пишу прямо на сайте, по этому статья будет обновляться примерно каждый день. Дополнения, уточнения и нормальная критика, приветствуется.

Начну:
Ham_Item_Holster - функция вызывается, когда мы прячем оружие в кобуру(пример со сменой ножа):
[spoiler][pawn]
  1. #include <amxmodx>

  2. #include <fakemeta>

  3. #include <hamsandwich>

  4.  

  5. #define is_valid_player(%0)     (1 <= %0 <= g_maxpls)

  6.  

  7. new g_maxpls;

  8.  

  9. public plugin_init(){

  10.  

  11.         RegisterHam(Ham_Item_Holster, "weapon_knife", "fw_knife_holstered", 1);

  12.        

  13.         g_maxpls = get_maxplayers();

  14.        

  15. }

  16.  

  17. public fw_knife_holstered(weapon_ent){

  18.  

  19.         if(!pev_valid(weapon_ent))

  20.                 return HAM_IGNORED;

  21.                

  22.         static id; id = get_pdata_cbase(weapon_ent, 41, 4);

  23.        

  24.         if(!is_valid_player(id))

  25.                 return HAM_IGNORED;

  26.        

  27.         //CODE

  28.        

  29.         return HAM_IGNORED;

  30. }
[/pawn]
Код для отлова момента смены оружия в кобуру(т.е. сменой на другое).Мне лично эта функция помогала "сбросить" гравитацию и скорость с игрока при смене оружия(я считаю это лучшим путем).[/spoiler]

Ham_Item_Deploy - функция вызывается при смене на нужное нам оружие(в данном случае нож):
[spoiler][pawn]
  1. #include <amxmodx>

  2. #include <fakemeta>

  3. #include <hamsandwich>

  4.  

  5. #define is_valid_player(%0)     (1 <= %0 <= g_maxpls)

  6.  

  7. new g_maxpls;

  8.  

  9. new v_model[]   = "models/knifes/v_knife.mdl";

  10. new w_model[]   = "models/knifes/p_knife.mdl";

  11.  

  12. public plugin_precache(){

  13.  

  14.         precache_model(v_model);

  15.         precache_model(w_model);

  16. }

  17.  

  18. public plugin_init(){

  19.  

  20.         RegisterHam(Ham_Item_Deploy, "weapon_knife", "fw_check_knife", 1);

  21.        

  22.         g_maxpls = get_maxplayers();

  23. }

  24.  

  25. public fw_check_knife(weapon_ent){

  26.  

  27.         if(!pev_valid(weapon_ent))

  28.                 return HAM_IGNORED;

  29.                

  30.         static id; id = get_pdata_cbase(weapon_ent, 41, 4);

  31.        

  32.         if(!is_valid_player(id))

  33.                 return HAM_IGNORED;

  34.                

  35.         set_pev(id, pev_viewmodel2, v_model);

  36.         set_pev(id, pev_weaponmodel2, w_model);

  37.        

  38.         return HAM_IGNORED;

  39. }
[/pawn]
В данном примере мы выставили модели ножу, который держит в руках игрок "models/knifes/v_knife.mdl" и "models/knifes/p_knife.mdl" для заменяя стандартные модели ножа.[/spoiler]

Ham_Player_Jump - вызывается каждый кадр прыжка.Их примерно у меня вызвалось ~60 кадров за секунду.
[spoiler][pawn]
  1. #include <amxmodx>

  2. #include <engine>

  3. #include <hamsandwich>

  4.  

  5. public plugin_init()    RegisterHam(Ham_Player_Jump,"player","fwrd_jump_post", 1);

  6.  

  7.  

  8. public fwrd_jump_post(id){

  9.        

  10.         if(~entity_get_int(id, EV_INT_flags) & FL_ONGROUND)

  11.                 return;

  12.                

  13.         new Float:Vel[3]

  14.         entity_get_vector(id, EV_VEC_velocity, Vel)

  15.         Vel[0] *= 1.20

  16.         Vel[1] *= 1.20

  17.         Vel[2] = 250.0

  18.        

  19.         entity_set_vector(id, EV_VEC_velocity, Vel)

  20.         entity_set_int(id, EV_INT_gaitsequence, 6)

  21. }
[/pawn]
В данном случае мы сделали autobhop, без остановок и с небольшим ускорением.[/spoiler]

Ham_CS_Player_ResetMaxSpeed - довольно-таки новая функция в hamsandwich модуле, вызывается в момент обнуления скорости, нужна версия amxmodx выше 1.8.2.

[spoiler][pawn]
  1. #include <amxmodx>

  2. #include <fakemeta>

  3. #include <hamsandwich>

  4.  

  5. #define MAX_PLAYERS     32

  6.  

  7. new bool:g_speed[MAX_PLAYERS+1] = false;

  8.  

  9. public plugin_init(){

  10.  

  11.         RegisterHam(Ham_CS_Player_ResetMaxSpeed, "player", "Check_speed", 0);

  12.        

  13.         register_concmd("say /speed", "speedhack");

  14. }

  15.  

  16. public speedhack(id){

  17.  

  18.         g_speed[id] = !g_speed[id];

  19.        

  20.         set_pev(id, pev_maxspeed, 2000.0);

  21. }

  22.  

  23. public Check_speed(id){

  24.        

  25.         if(g_speed[id])

  26.                 return HAM_SUPERCEDE;

  27.                

  28.         return HAM_IGNORED;

  29. }
[/pawn]
В данном примере мы создали булевую, при вводе в чат команды /test происходит выставление значении булевой нашей true/false и максимальная скорость с нашим новым значением 2000.0(по дефолту 250.0, но оружия такие как ак-47 - 240.0(вроде бы), а вот со scout - 260.0).И в Ham_CS_Player_ResetMaxSpeed проверяем нашу булевую и если наше условие подходит - суперсидим(возвращаем наше условие), чтобы не сбросилась скорость к стандартным значениям.[/spoiler]

Обновления: закончил список с изменениями параметров и добавил два недостающих примера.
Последний раз редактировалось Retro-kolt Lincoln 23 июл 2014, 22:13, всего редактировалось 1 раз.
Предлагаю услуги гаранта. Написание плагинов на заказ.
Статус:
на заслуженном отдыхе
Отзывы: Нажми
Обратиться ко мне: Нажми

- - - - - - - - - - - - - - - -
Если ваше ЛС было проигнорировано мною, знайте, оно мне не интересно.
Аватара пользователя
Retro-kolt Lincoln
 
Сообщения: 1283
Зарегистрирован: 28 авг 2010, 19:16
Благодарил (а): 321 раз.
Поблагодарили: 581 раз.
Опыт программирования: Больше трех лет
Языки программирования: ╚►Counter-Strike 1.6

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Asmodai » 24 июл 2014, 19:45

Safety1st писал(а):У меня ещё скорость 1000 периодически светится. А вообще идея интересная :thumbs_up Жаль, что FM куда хуже документирована(

Всмысле хуже? Вызовы g_engfuncs в сдк это и есть FM_ форварды. 1000 это просто начальное значение pev_maxspeed, устанавливаемое при спавне. Оно ничего не значит.
Аватара пользователя
Asmodai
Адмирал
 
Сообщения: 466
Зарегистрирован: 24 фев 2011, 20:48
Благодарил (а): 0 раз.
Поблагодарили: 393 раз.
Языки программирования: Counter-Strike 1.6

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Safety1st » 24 июл 2014, 19:50

Leonidddd писал(а):Не нужно с этим спорить.

Все перечисленные тобой случаи относятся к живому игроку с оружием. Там - да, оба форварда вызываются одинаковое число раз. Но GetMaxSpeed НЕ вызывается при выполнении ResetMaxSpeed в 3-х случаях (Вы должны зарегистрироваться, чтобы видеть ссылки.); потому ResetMaxSpeed вызывается чаще GetMaxSpeed по определению.

Asmodai писал(а):
Safety1st писал(а):Жаль, что FM куда хуже документирована(

Всмысле хуже? Вызовы g_engfuncs в сдк это и есть FM_ форварды.

Конечно, хуже. Код - это не документация.
GoldSrc Gaming Community
Аватара пользователя
Safety1st
 
Сообщения: 1958
Зарегистрирован: 08 окт 2011, 05:41
Откуда: Moscow
Благодарил (а): 1690 раз.
Поблагодарили: 933 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Leonidddd » 24 июл 2014, 20:10

Safety1st,

ResetMaxSpeed - для глобального отлова(т.е. когда нам нужно отловить обнуление скорости, вне зависимости от того, какое оружие держит игрок).

GetMaxSpeed - для отлова обнуления скорости в момент держания определенного оружия.

Каждый для отдельных случаев, на этом можно завершить.А кол-во вызовов у них почти одинаковое,т.к. GetMaxSpeed вызывается ещё при спауне оружия(ResetMaxSpeed не вызывается).
Конечно GetMaxSpeed оптимальнее,если нам нужно ловить только тот момент, когда в руках у игрока нож или ещё что-то одно, вот именно в этом его плюс, но если хукаем им все оружие, то явный минус.
Аватара пользователя
Leonidddd
Модератор
 
Сообщения: 2557
Зарегистрирован: 08 апр 2012, 18:13
Откуда: г. Запорожье
Благодарил (а): 192 раз.
Поблагодарили: 718 раз.

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Safety1st » 24 июл 2014, 20:37

Согласен, количество вызовов практически не отличается.

Leonidddd писал(а):GetMaxSpeed вызывается ещё при спауне оружия

Можно подтверждающий код? Я не нашёл.

Leonidddd писал(а):Конечно GetMaxSpeed оптимальнее,если нам нужно ловить только тот момент, когда в руках у игрока нож или ещё что-то одно, вот именно в этом его плюс.

Мало ключевой инфы в выводе, хотя я уже дважды подчёркивал. Главный плюс Ham_CS_Item_GetMaxSpeed перед Ham_CS_Player_ResetMaxSpeed - его наличие на AMXX ниже 1.8.3-dev, и этим плюсом будет долго оставаться.

Уже имея в плагине для AMXX 1.8.1 обработку Ham_CS_Item_GetMaxSpeed, я вряд ли буду добавлять отдельно Ham_CS_Player_ResetMaxSpeed ;)

Зачёркнуто:
[spoiler]Вообще, в случае Ham_CS_Player_ResetMaxSpeed мне куда больше нравится идея Asmodai про FM_SetClientMaxspeed: есть везде, там сразу видно, какую скорость dll'kа собирается назначить и легко предотвратить вызов и установить свою скорость без лишних усилий. Я бы на твоём месте сделал оговорку в посте про форвард, что описан только для учебных целей, а вместо него рекомендуется использовать либо FM_SetClientMaxspeed, либо Ham_CS_Item_GetMaxSpeed.[/spoiler]
Последний раз редактировалось Safety1st 25 июл 2014, 00:04, всего редактировалось 1 раз.
GoldSrc Gaming Community
Аватара пользователя
Safety1st
 
Сообщения: 1958
Зарегистрирован: 08 окт 2011, 05:41
Откуда: Moscow
Благодарил (а): 1690 раз.
Поблагодарили: 933 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Leonidddd » 24 июл 2014, 21:33

Можно подтверждающий код? Я не нашёл.

Можно, вот куски(могу ещё добавить):
[spoiler]тут я не так понял, признаю.[/spoiler]
Главный плюс Ham_CS_Item_GetMaxSpeed перед Ham_CS_Player_ResetMaxSpeed - его наличие на AMXX ниже 1.8.3-dev, и этим плюсом будет долго оставаться.

С этим не спорю, только могу сказать, что стоит только продвигаться вперед.
Последний раз редактировалось Leonidddd 28 июл 2014, 01:03, всего редактировалось 2 раз(а).
Аватара пользователя
Leonidddd
Модератор
 
Сообщения: 2557
Зарегистрирован: 08 апр 2012, 18:13
Откуда: г. Запорожье
Благодарил (а): 192 раз.
Поблагодарили: 718 раз.

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Asmodai » 24 июл 2014, 22:12

Leonidddd, это объявление, а не вызов. Вызов только в ResetMaxSpeed есть.

Leonidddd писал(а):стоит только продвигаться в перед.

Во что во что продвигаться?
Аватара пользователя
Asmodai
Адмирал
 
Сообщения: 466
Зарегистрирован: 24 фев 2011, 20:48
Благодарил (а): 0 раз.
Поблагодарили: 393 раз.
Языки программирования: Counter-Strike 1.6

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Leonidddd » 24 июл 2014, 22:18

Asmodai, не оставаться на старых билдах я имел ввиду.Все равно при создании оружия объявление произойдет и выставление значения нового через GetMaxSpeed будет.
[spoiler]Какой внимательный. :-D[/spoiler]
Аватара пользователя
Leonidddd
Модератор
 
Сообщения: 2557
Зарегистрирован: 08 апр 2012, 18:13
Откуда: г. Запорожье
Благодарил (а): 192 раз.
Поблагодарили: 718 раз.

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Safety1st » 24 июл 2014, 22:25

Leonidddd писал(а):Asmodai, не оставаться на старых билдах я имел ввиду.

Я лично с этим согласен. Но 99% серверов стоят на хостингах, а у них со свежими билдами глухо. Да и кое-какие затруднения при переходе есть; для нас-то небольшие, а для рядовых пользователей сложности.

Leonidddd писал(а):и выставление значения нового через GetMaxSpeed будет.

Будет, если будет deploy оружия. Но создание entity или её спавн функцию GetMaxSpeed не вызывают.
Последний раз редактировалось Safety1st 24 июл 2014, 22:30, всего редактировалось 4 раз(а).
GoldSrc Gaming Community
Аватара пользователя
Safety1st
 
Сообщения: 1958
Зарегистрирован: 08 окт 2011, 05:41
Откуда: Moscow
Благодарил (а): 1690 раз.
Поблагодарили: 933 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Asmodai » 24 июл 2014, 22:26

Аватара пользователя
Asmodai
Адмирал
 
Сообщения: 466
Зарегистрирован: 24 фев 2011, 20:48
Благодарил (а): 0 раз.
Поблагодарили: 393 раз.
Языки программирования: Counter-Strike 1.6

Re: Изучение модуля Hamsandwich с нуля [12.08.2013]

Сообщение Leonidddd » 24 июл 2014, 22:30

[spoiler]Ушёл на долгий отпуск и изучение С++.[/spoiler]
Аватара пользователя
Leonidddd
Модератор
 
Сообщения: 2557
Зарегистрирован: 08 апр 2012, 18:13
Откуда: г. Запорожье
Благодарил (а): 192 раз.
Поблагодарили: 718 раз.

Пред.След.

Вернуться в Статьи / фрагменты кода

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron