Доброго дня.
Итак, сегодня речь пойдет о контроле нанесенного игроку урона. SA:MP (а значит - и адаптации) при получении игроком урона незамедлительно запускает коллбэк OnPlayerTakeDamage, у которого есть несколько входных параметров:- playerid - ID игрока, которому был нанесен урон.
- issuerid - ID игрока, который нанес урон. Если игрок пострадал от падения, взрыва и т.п. - в данный параметр будет передано значение INVALID_PLAYER_ID.
- amount - количество нанесенного урона в виде числа с плавающей точкой.
- weaponid - ID оружия, которым был нанесен урон, либо ID причины нанесения урона. Более подробно об этом можно прочитать в статье на SA:MP Wiki.
Разбирать, как же все это работает, я предлагаю на конкретном примере. И примером таким станет написание системы нанесения ранений.
Собственно, в обобщенном виде алгоритм действий будет таков:- Если игрок получает урон - с шансом 1 к 2 он упадет в обморок.
- Если игрок падает в обморок - заморозить его любым доступным способом на определенное время. В примере время обморока будет выбрано случайно.
- Если время обморока закончилось - разморозить игрока.
Итак, приступим. Подключаем библиотеку a_samp. Работы в других коллбэках нам практически не нужны. Для собственной страховки в OnPlayerSpawn можно вызвать функцию ClearAnimations.
Итак, первоначально - определяем время и шанс обморока. Минимальное время в моем примере - 15 секунд, максимальное - 1 минута.
PHP код:
public OnPlayerTakeDamage(playerid, issuerid, Float: amount, weaponid)
{
new ObmorokTime = random(45)+15;
new Obmorok = random (3);
И в этом месте на момент написания скрипта я задумался. Есть шанс, что нанесенного урона хватит, чтобы убить игрока, однако для него уже будет вызвана анимация, что может привести к отсутствию вызова OnPlayerDeath. Проблема решилась просто и изящно - если у игрока будет менее 10 HP, скрипт просто не будет вызван. Точно также анимация будет вызвана и для водителя, что нам не нужно - такую проверку мы тоже поставим.
PHP код:
new Float:HP;
GetPlayerHealth(playerid, HP);
if (HP >=10 && GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)
{
Далее через switch проверяем, упал все-таки в обморок игрок или нет. Если упал - очищаем ему текущую анимацию, на время ObmorokTime применяем к нему анимацию, которая не позволит игроку двигаться, и таймер для сброса этой анимации в указанное время.
PHP код:
switch (Obmorok)
{
case 2:
{
ClearAnimations(playerid);
ApplyAnimation(playerid, "CRACK", "crckdeth2", 4.1, 0, 1, 1, 1, ObmorokTime*1000, 1);
SetTimerEx ("ClearAnimation", ObmorokTime*1000, false, "d", playerid);
Ну, и для большей информативности - добавим информацию ранившему и раненному. Если же раненный сам виноват - следует ввести проверку и на это. Резервируем три переменные, проверяем ID атаковавшего и в зависимости от этого выводим сообщения о ранении.
PHP код:
new string[128], victim[MAX_PLAYER_NAME], attacker[MAX_PLAYER_NAME];
GetPlayerName(playerid, victim, sizeof (victim));
if (issuerid != INVALID_PLAYER_ID)
{
GetPlayerName(issuerid, attacker, sizeof (attacker));
format(string, sizeof(string), "%s ранил Вас!", attacker);
SendClientMessage(playerid, 0xFF110000, string);
format(string, sizeof(string), "Вы ранили %s!", victim);
SendClientMessage(issuerid, 0xFF110000, string);
}
else
{
SendClientMessage(playerid, 0xFF110000, "Вы ранены!");
}
}
}
}
return 1;
}
За этим все! Больше от программиста не требуется ничего, скрипт будет успешно работать, что уже доказано использованием его на нашем проекте уже больше года.
PHP код:
#include <a_samp>
public OnFilterScriptInit()
{
print("\n--------------------------------------");
print("Обморок от ранения");
print("--------------------------------------\n");
return 1;
}
public OnFilterScriptExit()
{
return 1;
}
public OnPlayerSpawn (playerid)
{
ClearAnimations(playerid);
return 1;
}
public OnPlayerTakeDamage(playerid, issuerid, Float: amount, weaponid)
{
new ObmorokTime = random(45)+15;
new Obmorok = random (3);
new Float:HP;
GetPlayerHealth(playerid, HP);
if (HP >=10 && GetPlayerState(playerid) == PLAYER_STATE_ONFOOT)
{
switch (Obmorok)
{
case 2:
{
ClearAnimations(playerid);
ApplyAnimation(playerid, "CRACK", "crckdeth2", 4.1, 0, 1, 1, 1, ObmorokTime*1000, 1);
SetTimerEx ("ClearAnimation", ObmorokTime*1000, false, "d", playerid);
new string[128], victim[MAX_PLAYER_NAME], attacker[MAX_PLAYER_NAME];
GetPlayerName(playerid, victim, sizeof (victim));
if (issuerid != INVALID_PLAYER_ID)
{
GetPlayerName(issuerid, attacker, sizeof (attacker));
format(string, sizeof(string), "%s ранил Вас!", attacker);
SendClientMessage(playerid, 0xFF110000, string);
format(string, sizeof(string), "Вы ранили %s!", victim);
SendClientMessage(issuerid, 0xFF110000, string);
}
else
{
SendClientMessage(playerid, 0xFF110000, "Вы ранены!");
}
}
}
}
return 1;
}
К сожалению, табуляция при постинге съехала, поэтому если нужно - табулируйте сами.
Вопросы принимаются в этой теме.