PDA

Просмотр полной версии : [Вопрос] Pickups



vovandolg
07.09.2016, 16:02
Делаю систему лута на пикапах, что то не совсем получается, вот код:



new pic_loot[MAX_PICKUPS], one_loot;

//Вот так я создаю пикапы при смерти
pic_loot[one_loot++] = CreatePickup(1580, 22, pos_x[playerid], pos_y[playerid] + 2.0, pos_z[playerid], 0);


public OnPlayerPickUpPickup(playerid, pickupid)
{
//printf("1 pickupid: %i| pic_loot[one_loot]: %i| one_loot: %i|", pickupid, pic_loot[one_loot], one_loot);
if(pic_loot[1] <= pickupid <= pic_loot[one_loot])
{
//printf("2 pickupid: %i| pic_loot[one_loot]: %i| one_loot: %i|", pickupid, pic_loot[one_loot], one_loot);
DestroyPickup(pickupid);
one_loot--;
//printf("3 pickupid: %i| pic_loot[one_loot]: %i| one_loot: %i|", pickupid, pic_loot[one_loot], one_loot);
return SCM(playerid, -1, !"[TEST] Уничтожено!");
}
return 1;
}



Когда я создам один пикап всё гуд, он подбирается и удаляется, когда два или более они не удаляются, как так сделать чтобы всё удалялось?
(пример не где взять поэтому заколбасил с нуля:pardon:)

DeimoS
07.09.2016, 17:54
Эмм, когда ты создаёшь пикап, в качестве индекса массива ты используешь значение переменной one_loot. А когда удаляешь, уже опираешься на ID пикапа. Где логика?


Я бы советовал использовать foreach и не париться. Создай итератор и вноси в него данные о пикапе, а после удаляй

Fallen A.
07.09.2016, 18:38
Эмм, когда ты создаёшь пикап, в качестве индекса массива ты используешь значение переменной one_loot. А когда удаляешь, уже опираешься на ID пикапа. Где логика?


Я бы советовал использовать foreach и не париться. Создай итератор и вноси в него данные о пикапе, а после удаляй

А еще создание и удаление может идти неравномерно, поэтому присутствует баг, в виде выхода за пределы массива.

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

Пересмотрел код: даже пересоздание случайного пикапа возможно.

vovandolg
07.09.2016, 18:44
А есть урок где нибудь как полноценно или правильно пользоваться foreach функциями/итераторами?

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

p.s. вариант который мне надо сделать схож с этим что ниже?


Нет, это не прокатит. Твою проблему решить можно множеством способов, но я покажу самый удобный:
Создадим массив итераторов TeamPlayer (константы MAX_TEAMS и MAX_TEAM_PLAYERS нужно заменить на свои):

new Iterator:TeamPlayer[MAX_TEAMS]<MAX_TEAM_PLAYERS>;

К сожалению, реализовать инициализацию массива итераторов во время компиляции у Y_Less не получилось, поэтому инициализируем при запуске:


public OnGameModeInit()
{
Iter_Init(TeamPlayer);
}

Функция добавления игрока в команду (содержимое нужно добавить к своей)

stock AddPlayerToTeam(playerid, teamid)
{
Iter_Add(TeamPlayer[teamid], playerid);
}

Функция удаления игрока из команды (содержимое нужно добавить к своей):

stock RemovePlayerFromTeam(playerid, teamid)
{
Iter_Remove(TeamPlayer[teamid], playerid);
}

Тогда твой код можно будет написать так:

SetupFG(Iter_Random(TeamPlayer[1]));

Суть проста: используйте итераторы по полной, это удобно. И, чаще всего, это положительно сказывается на производительности.

DeimoS
07.09.2016, 18:58
А еще создание и удаление может идти неравномерно, поэтому присутствует баг, в виде выхода за пределы массива.

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

Пересмотрел код: даже пересоздание случайного пикапа возможно.

Я, собственно, это и имел ввиду. Если на сервере будет создан пикап от этой системы, достаточно создать 1 пикап, который к этой системе не относится, всё, код работать будет неверно.



А есть урок где нибудь как полноценно или правильно пользоваться foreach функциями/итераторами?

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

p.s. вариант который мне надо сделать схож с этим что ниже?






Да

vovandolg
07.09.2016, 19:09
Допустим вот что наколякал:



#define MAX_LOOT (100)

new Iterator:PickupLoot[MAX_LOOT]<MAX_PICKUPS>;

public OnGameModeInit()
{
Iter_Init(PickupLoot);
return 1;
}

stock CreatePickupLoot(model, type, Float:X, Float:Y, Float:Z, virtualworld = 0)
{
new pickID;
pickID = CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld);
Iter_Add(PickupLoot[pickID], pickID);
return 1;
}

stock DestroyPickupLoot(pickupid)
{
Iter_Remove(PickupLoot[pickupid], pickupid);
DestroyPickup(pickupid);
return 1;
}


public OnPlayerPickUpPickup(playerid, pickupid)
{
if(PickupLoot[pickupid] == pickupid) //Вот тут как правильно оформить проверку на соответствующий ID?
{
DestroyPickupLoot(PickupLoot[pickupid]);
return SCM(playerid, -1, !"[TEST] Del ...");
}
return 1;
}

DeimoS
07.09.2016, 19:18
Эмм, зачем ты создал MAX_LOOT? Двумерный массив тут не нужен. Найди тему о foreach на sa-mp.com и прочти её. Там всё о итераторах написано, если мне память не изменяет.

Как-то так:

new Iterator:PickupLoot<MAX_PICKUPS>;

stock CreatePickupLoot(model, type, Float:X, Float:Y, Float:Z, virtualworld = 0)
{
Iter_Add(PickupLoot, CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld));
return 1;
}

public OnPlayerPickUpPickup(playerid, pickupid)
{
foreach(new i: PickupLoot)
{
if(i != pickupid) continue;
DestroyPickup(i);
Iter_SafeRemove(PickupLoot, i, i);
return SCM(playerid, -1, !"[TEST] Del ...");
}
return 1;
}

vovandolg
07.09.2016, 20:28
Как-то так:

new Iterator:PickupLoot<MAX_PICKUPS>;

stock CreatePickupLoot(model, type, Float:X, Float:Y, Float:Z, virtualworld = 0)
{
Iter_Add(PickupLoot, CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld));
return 1;
}

public OnPlayerPickUpPickup(playerid, pickupid)
{
foreach(new i: PickupLoot)
{
if(i != pickupid) continue;
DestroyPickup(i);
Iter_SafeRemove(PickupLoot, i, i);
return SCM(playerid, -1, !"[TEST] Del ...");
}
return 1;
}

Благодарствую, ещё момент есть в игре,
если ставить на модель ID капсулы или оружия начинает выдавать прикалюны разные как в сингле, это как нибудь отключается?

DeimoS
08.09.2016, 12:45
Благодарствую, ещё момент есть в игре,
если ставить на модель ID капсулы или оружия начинает выдавать прикалюны разные как в сингле, это как нибудь отключается?

Хмм, попробуй поменять тип пикапа. То ли 23, то ли 21 не имеет никакого эффекта

vovandolg
08.09.2016, 14:17
Вот блин, а я то думал как у меня на рп брались эти пикапы и не давали эффектов, а тут от типа зависит,
23 не очень подошёл, 21 не было, поставил 19 то что нужно =)

Всё спасибо, тема решена можно закрывать.