[SourcePawn] Уроки (Содержание)

R1KO

fuck society
Команда форума
Сообщения
9,016
Реакции
6,897
[SourcePawn] Уроки - Содержание

  1. Основы языка (Часть 1) (Часть 2)
  2. Установка и компиляция плагинов + Ошибки компиляции
  3. События (Events)
  4. Форматирование текста и мультиязычность
  5. DataPack
  6. Таймеры
  7. Панели и меню
  8. Структуры Key Values
  9. ADT Array (ArrayList)
  10. ADT Trie (StringMap)
  11. Админ меню
  12. metodmap
  13. Работа с базами данных
  14. Работа с куками (clientprefs)
  15. API (natives, forwards, functions)
  16. Отладка (Debug)
Другие уроки:

TODO:
  • Работа с файлами
  • Структуры Key Values

Возможны изменения и дополнения.

Без номера - не определился в последовательности.
Кто что еще хочет увидеть - пишите.

Уроки будут выходить в txt виде, а тех уроках где нужна визуализация будет видео формат.
 
Последнее редактирование:

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
@R1KO,
У меня один, для меня очень серьёзный вопрос. Как определить какие таймеры запущены?
И еще вопрос - могу я ID таймера объявить не HANDLE а int или new?
Например:
C-подобный:
new таймер;
таймер = CreateTimer("Функция",.......);

Я здесь четко знаю ID таймера. И по нему могу отследить работу этого таймера, со всеми вытекающими.
А HANDE я не врубаюсь. Не могу понять.

И третье - как правильно получить работает таймер или нет
if (Timers[client] != null)
или так
if (Timers[client] != INVALID_HANDLE)
как правильнее?

Меня этот INVALID_HANDLE просто убивает.
 
Последнее редактирование:

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
Несколько таймеров создаются CreateDataTimer (данных несколько - приходится паковать).
объявление
new Handle:Timer[MAXPLAYERS + 1] = INVALID_HANDLE;

C-подобный:
public Action:OnRoundStart(Handle:event, const String:name[], bool:dontBroadcast){   // при рестарте хочу сбросить (поубивать) все таймеры

for(new i = 1; i <= MaxClients; i++){                      // цикл по всем игрокам

if (Timer[i] != INVALID_HANDLE){                      // если например этот таймер запущен у кого то        
KillTimer(Timer[i]);                                                     // убиваем таймер
Timer[i] = INVALID_HANDLE;

L 10/17/2016 - 17:59:00: [SM] Exception reported: Invalid timer handle 130c02d3 (error 3)
L 10/17/2016 - 17:59:00: [SM] Call stack trace:
L 10/17/2016 - 17:59:00: [SM] [0] KillTimer
такого плана ошибка. Где косяк?
 
Последнее редактирование:

AlmazON

Не путать с самим yand3xmail
Сообщения
5,127
Реакции
2,338
могу я ID таймера объявить не HANDLE а int или new
Таймер возвращает Handle, иначе будет несовпадение тегов. Да и какой в этом смысл? Через int таймер не остановить, а условно и сам можешь подписать, приравняв глобальную переменную к "номеру" работающего таймера.
if (Timers[client] != null)
или так
if (Timers[client] != INVALID_HANDLE)
Первое - новый синтаксис, второе - старый. Разницы абсолютно никакой.
После выполнения таймера (не повторяющегося) также необходимо делать сброс его Handle (внутри таймера):
C-подобный:
Timer[i] = INVALID_HANDLE;
 

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
Все таймеры повторяющиеся. Про разовые зачем бы я писал?
 
Последнее редактирование:

AlmazON

Не путать с самим yand3xmail
Сообщения
5,127
Реакции
2,338
Все таймеры повторяющиеся
Частая ошибка: флаг TIMER_FLAG_NO_MAPCHANGE у таймера, а его Handle не сброшено в OnMapEnd().
Разовые зачем бы я писал?
Оффтоп Хочешь конкретный, точный ответ - изволь приложить код, где фигурируют таймеры и их Handle.
 

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
Может быть нужно в OnMapEnd() это сделать. Я не делал там.
 

R1KO

fuck society
Команда форума
Сообщения
9,016
Реакции
6,897
@tonline_kms65, покажи код создания таймера и других действий с ними
 

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
@R1KO,
Ок. Домой приеду,покажу. Я поэтому и хотел делать в цикле такие дела. Но не хочет здесь цикл на бесконечный зацикливаться. Сколько не пробовал,где то ограничение стоит.
--- Добавлено позже ---
Что вообще такое это самое Handle.
Это переменная, функция или еще что.
Не могу сообразить что это за хрень.
Если понять что это, то возможно и проблемы отпадут.
Написали бы тутор по это. Таких как я наверняка много. А так просто тыкать абы что это не дело. Нужно знать что это такое.
 
Последнее редактирование:

Grey83

Ленивая и невнимательная жопа
Сообщения
4,827
Реакции
2,837
PHP:
new Handle:Timer[MAXPLAYERS + 1] = INVALID_HANDLE;
Насколько я помню при использовании new переменная всегда равняется нулю, строка - нулевой строке, а хэндл - INVALID_HANDLE.
Плюс тут у тебя массив, которому назначают значение обычно так:
PHP:
new SomeInt[SomeConst] = {-1, ...};
new Float:SomeFloat[AnotherConst] = {0.1, ...};
new String:SomeString[][] = {"FistString", "SecondString", "ThirdString"};
new bool:SomeBool[OneMoreConst] = {true, ...}
Если значения массива все одинаковые и известен размер массива, то достаточно только один раз указать это значение. В случае разных значений делается как и со строчной переменной в примере.

Так вот я к чему: у тебя при компиляции не всплывало предупреждение, что у тебя размеры массива не соответствуют или аналогичное что-то?
 

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
у тебя при компиляции не всплывало предупреждение, что у тебя размеры массива не соответствуют или аналогичное что-то?
Конечно нет. Если бы сообщение было, то и проблем бы не возникло. Компилятор отрабатывает четко, без ошибок.

@R1KO,
Создаю таймер:
C-подобный:
//------------------------------------------------------------------------------
LoopShowHudCountSM_Grenade(client, ent) {                                       //
int iCount = sm_count[ent];   // это кол-во гранат этого типа (дымовые). Глобал. данные изменяются при создании гранат++ и их уничтожении--.
if (iCount > 0){

if (camera[client] == true){                                                    // в HUD  один раз
SetHudTextParamsEx(0.85, 0.85, 3.0, {0,147,3,255}, {181,255,84,255}, 2, 0.1, 0.1, 0.1);
ShowHudText(client, -1, "Smoke %i", iCount);
}
if (ShowHud_smokeGrenadeCount[client]  != INVALID_HANDLE){       // вот этот головняк. Если таймер запущен
KillTimer(ShowHud_smokeGrenadeCount[client]);                                       //  убиваю его
ShowHud_smokeGrenadeCount[client]  = INVALID_HANDLE;               // очищаю данные
}

new Handle:Pack3;
ShowHud_smokeGrenadeCount[client] = CreateDataTimer(3.0, timer_LoopShowHudCountSM_Grenade, Pack3, TIMER_FLAG_NO_MAPCHANGE|TIMER_DATA_HNDL_CLOSE);
WritePackCell(Pack3, GetClientUserId(client));                // Пакуем обновленные данные в таймер
WritePackCell(Pack3, ent);
  }
return;
}
//------------------------------------------------------------------------------
public Action:timer_LoopShowHudCountSM_Grenade(Handle:timer, any:Pack3) {
ResetPack(Pack3);                                                   
int iClient      = ReadPackCell(Pack3);
int iEnt         = ReadPackCell(Pack3);
iClient          = GetClientOfUserId(iClient);
LoopShowHudCountSM_Grenade(iClient, iEnt);
}

Почему сделал так? Я пробовал делать в самом таймере TIMER_REPEAT.
Чем-то мне этот вариант не понравился. Почему то я эту затею оставил.
Поэтому остановился на своём, он мне как то привычнее и понятнее.
--- Добавлено позже ---
Убиваю таймеры при:
1. Разрушении Дрона (с приатаченными гранатами, и соответственно запущенными таймерами)
2. Если граната к которой привязан этот таймер брошена Дроном и взорвалась.(Во, кстати, гранат может быть не одна, может быть отсюда и косяк? В таймер я получаю данные только о количестве гранат для определенного Дрона)
3. При рестарте (если таймеры вдруг остались запущенны, а такое уже было)
Больше таймеры я нигде не трогаю.

Сделал краткое видео для именно этих таймеров.
 
Последнее редактирование:

Kruzya

Raspberry Pi 4
Команда форума
Меценат
Сообщения
10,550
Реакции
8,726
@tonline_kms65, Ты реально пишешь код без табуляции, или как? Неудобно же читать.
Зачем ты вынес "главную функцию" таймера в отдельную функцию? Которая LoopShowHudCountSM_Grenade. И не смешивай старый синтаксис с новым:
PHP:
public Action:timer_LoopShowHudCountSM_Grenade(Ha
<...>
int iClient      = ReadPackCell(Pack3);
int iEnt         = ReadPackCell(Pack3);
Серьёзно, зачем функцию объявляешь по старому синтаксису, записывая то, что она вернёт через двоеточие, и тип параметров аргументов тоже, а в самой функции объявляешь переменные по новому синтаксису? Получается натуральная "лапша" из кода.
 
Последнее редактирование:

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
@CrazyHackGUT,

А ты бы как сделал? Запускать из основной вспомогательную? Я же говорю - почему то меня это не устроило. Я не помню уже почему.
Я так и делал сначала. потом плюнул и вернулся к своему проверенному.
Старый, новый, работает - работает. И так головняка хватает помимо sourcepawnа. Да честно сказать я даже и не знаю где там новый где старый. Мне как то по барабану:biggrin:. Я даже и не знал что там есть где то новый а где-то старый. Для меня все едино. Ну вооооообще.
Всегда число - интегром, строка - строкой, бол - болом и т.д, поэтому этот инвалид HANDLE меня загрузил просто по полной. Всегда старался держаться от него подальше, но вот пришлось встретится, т.к. другого решения пока не вижу.
Не могу сообразить что это такое и всё. Возможно это огромная помощь и облегчение задачи, но для меня это есть проблема.

Насчет табуляции, всегда без отступов, уж не обессудь.
У меня синтаксис Python, я всегда в нем работал. Подсветка намного удачнее.
Я на будущее, для этого сайта, буду переводить в другой синтаксис.
 
Последнее редактирование:

tonline_kms65

Заблокирован
Сообщения
65
Реакции
10
@R1KO,
Я попробую еще один вариант, если не получится я тебе скину код который непосредственно касается этой проблемы. Подбирание с земли ENT, запуск таймера, выброс ENT, разрушение ENT. (ENT гранат)
Весь код это уже почти 2000 строк.
 
Сверху