PDA

Просмотр полной версии : [Вопрос] Убийство командой



vovandolg
08.04.2016, 06:28
Есть же /sethp и ей подобные, так вот что я хочу сделать.
Надо так чтобы килл другого игрока командой засчитало ещё и кто убил, не просто переменные забить как делается,
а прогнать каким то образом через калбэк OnPlayerDeath(playerid, killerid, reason);
Если юзать выдачу HP и сразу калбэк то получается абракадабра вплоть до багов или киков от фейк киллов,
если юзать чисто OnPlayerDeath то не че не происходит(оно и ежу понятно он вызывается при смерти, а не для смерти),
это вообще реализуемо или я только зря теряю время?

DeimoS
08.04.2016, 06:33
А теперь ещё раз и по-русски

vovandolg
08.04.2016, 07:33
ааа...
когда убиваешь стволом другого игрока срабатывает OnPlayerDeath
когда сетаешь хп другой игрок помирает от INVALID_PLAYER_ID
а мне надо сделать в команде(и в одном паблике потом ещё) имитацию убийства,
что Вася убил Петю и на выбор чем он убил...

DeimoS
08.04.2016, 09:32
ааа...
когда убиваешь стволом другого игрока срабатывает OnPlayerDeath
когда сетаешь хп другой игрок помирает от INVALID_PLAYER_ID
а мне надо сделать в команде(и в одном паблике потом ещё) имитацию убийства,
что Вася убил Петю и на выбор чем он убил...

Ну вот сама функция

stock FakeKill(killer, killee, weaponid)//killer - ID убийцы | killee - ID умершего игрока.
{
if(!IsPlayerConnected(killer))//Если убийца не подключён
{
SendDeathMessage(INVALID_PLAYER_ID, killee, WEAPON_DROWN);//Указываем про самоубийство
return 0;
}
if(!IsPlayerConnected(killee))//Если убитый не подключён
{
return -1;
}
else
{
SendDeathMessage(killer, killee, weaponid);
//И тут остальные действия, связанные с убийством (выдача денег/работа с другими переменными)
}
return 1;
}
Использование:

FakeKill(ID_убийцы, ID_убитого, ID_оружия);
Пример использования:

CMD:fakekill(playerid,params[])
{
new killer,
killee,
weaponid;
if(!sscanf(params, "iii", killer, killee, weaponid))
return SendClientMessage(playerid, 0x0000FFFF, "Использование: {FFFFFF}/kill <ID убийцы> <ID убиваемого игрока> <ID оружия>");
if(FakeKill(killer, killee, weaponid) == -1) return SendClientMessage(playerid, 0xFF0000FF, "Ошибка: {FFFFFF}ID, который вы указали в качестве убийцы, не подключён");
SendClientMessage(playerid, 0x0000FFFF, "Использование: {FFFFFF}Вы совершили фейковое убийство");
return 1;
}

Функция возвращает:
-1 - если убитый игрок не подключён (никаких действий не произойдёт)
0 - если убийца не подключён (отправит в чат сообщение о суициде
1 - если оба игрока подключены (отправит сообщение о убийстве

vovandolg
08.04.2016, 09:50
Мне надо чтобы при сетании на ноль калбэк OnPlayerDeath прогоняло весь, а не вывод мессэйджа о смерти)
Так как в этом калбэке много инфы в посмертии, а такие мелочи я и сам могу сделать)

TheMallard
08.04.2016, 10:01
Могу предположить что можно завести спец-переменную для таких случаев и записать админа-убийцу.

Типа:



public OnPlayerDeath(...)
{
new my_killerid;

if(p_info[playerid][killedByAdmin] != -1)
my_killerid = p_info[playerid][killedByAdmin];
else
my_killerid = killerid;

.....
}

SliM
08.04.2016, 10:02
https://wiki.sa-mp.com/wiki/CallRemoteFunction_RU
https://wiki.sa-mp.com/wiki/CallLocalFunction_RU это не проще?

TheMallard
08.04.2016, 10:08
Тогда уж легче напрямую вызвать, но зачем два раза вызывать калбэк?

SliM
08.04.2016, 10:17
Тогда уж легче напрямую вызвать, но зачем два раза вызывать калбэк?
Вызывая напрямую можно всю динамическую память забить, если быть кривожопомруком. А если ты не кривожопорук, то напрямую точно не будешь вызывать:) Мое предложение итак бред, понял это как только нажал на кномпку "отправить сообщение", после установки нуль-ХП игроку он умрет и колбэк OnPlayerDeath выполнится, после чего еще раз выполнится (CallLocalFunction) и оба раза с разными аргументами:) Нужен костыль с перехватами и подменой аргументов.

Добавлено:

Такая последовательность событий мне пришла в голову, состоит из 5-ти шагов.
шаг 1:

new
player_killerid [MAX_PLAYERS],
player_reason [MAX_PLAYERS]
;
шаг 2:

CMD: kill()
{
PlayerFakeDeath (params [0], playerid, params [1]) // в params [0] ид убитого в [1] причина (оружие).
}
шаг 3:

PlayerFakeDeath (playerid, killerid, reason)
{
SetPlayerHealth (playerid, 0.0);
player_killerid [playerid] = killerid;
player_reason [playerid] = reason;
}
шаг 4

public OnPlayerDeath (playerid, killerid, reason)
{
if (player_killerid [playerid] != 0xFFFF)
killerid = player_killerid [playerid];
if (player_reason [playerid] != 0xFF)
reason = player_reason [playerid];

//ваш код
}
шаг 5

public OnPlayerSpawn (playerid)
{
player_killerid [playerid] = 0xFFFF;
player_reason [playerid] = 0xFF;

//ваш код
}
и лучше перестраховаться проверкой на INVALID_PLAYER_ID, дабы избежать выхода за пределы массивов player_killerid и player_reason

vovandolg
08.04.2016, 11:39
Могу предположить что можно завести спец-переменную для таких случаев и записать админа-убийцу.

Типа:



public OnPlayerDeath(...)
{
new my_killerid;

if(p_info[playerid][killedByAdmin] != -1)
my_killerid = p_info[playerid][killedByAdmin];
else
my_killerid = killerid;

.....
}


Такое тоже умеем)
Вот только в паблике этого калбэка свои проверки и переменные которые обязательны к воспроизведению при такой смерти)


Вызывая напрямую можно всю динамическую память забить, если быть кривожопомруком. А если ты не кривожопорук, то напрямую точно не будешь вызывать:)
У меня вызов идёт из команды и в посмертии от сетания, рекурсии не будет, единственное что калбэк срабатывает два раза,
Позже вечерком ещё тестану как замыслил, отпишусь...

- - - Добавлено - - -

Как бы так вам толком объяснить чтобы не писали лишний мусор,
игрок умирает и идёт запись в аргументы OnPlayerDeath(playerid, killerid, reason);
При сетании идут аргументы самоубийства или поцеловал землю вроде того и убийца 0xFFFF,
а мне нужно чтобы в аргументы писануло кто и как убил, вот и вызываю второй раз этот калбэк!:pleasantry:

SliM
08.04.2016, 11:43
я ведь написал пример, скорее всего рабочий:)


PlayerFakeDeath (3, 5, 38); //получаем - игрок с идом 5 убил игрока с идом 3 из минигана

аргументы в том-же порядке что и в OnPlayerDeath, для удобства

vovandolg
08.04.2016, 12:03
Версия как и у DeimoS, но мысля появилась кое какая.
Разве что сделать так


stock __death_public(playerid,killerid,reason)
{
//весь код из паблика сюда
}

public OnPlayerDeath(playerid, killerid, reason)
{
if(!GetPVarInt(playerid,"DD"))
{
DeletePVar(playerid,"DD");
__death_public(playerid,killerid,reason);
}
return 1;
}

//А в команде флаг pvar
if(amount <= 0.0)
{
SetPVarInt(playerid,"DD",1);
__death_public(playerid,killerid,reason);//и тут указывать что на ум придёт)
}
SetPlayerHealth(plaerid, amount);


Так меньше нагрузки будет я думаю)

DeimoS
08.04.2016, 15:09
Версия как и у DeimoS, но мысля появилась кое какая.
Разве что сделать так


stock __death_public(playerid,killerid,reason)
{
//весь код из паблика сюда
}

public OnPlayerDeath(playerid, killerid, reason)
{
if(!GetPVarInt(playerid,"DD"))
{
DeletePVar(playerid,"DD");
__death_public(playerid,killerid,reason);
}
return 1;
}

//А в команде флаг pvar
if(amount <= 0.0)
{
SetPVarInt(playerid,"DD",1);
__death_public(playerid,killerid,reason);//и тут указывать что на ум придёт)
}
SetPlayerHealth(plaerid, amount);


Так меньше нагрузки будет я думаю)

Именно это я и подразумевал под

//И тут остальные действия, связанные с убийством (выдача денег/работа с другими переменными)
Вывод сообщения о смерти - лишь копирование тех действий, которые бы произошли при обычной смерти, если у тебя DM мод с килл-листом. Да и просто пример.




Либо можно просто продублировать код коллбэка OnPlayerDeath в команде. Точнее, только то, что тебе нужно будет.