[SM] Случайное оружие

diller110

Добрая душа
Сообщения
353
Реакции
278
Здравствуйте, помогите пожалуйста с кодом, а именно концепцией решения проблемы.
Плагин выдает оружие при вводе команды, оружие выбирается рандомно, но не имеет ограничения за раунд.
Набросок плагина вот:
public Action:Command_DropJoke(client, args)
{
if (IsPlayerAlive(client)) {
if (g_Drop == 1) {
new String:DropWinner[MAX_NAME_LENGTH];
GetClientName(client, DropWinner, sizeof(DropWinner));
Client_RemoveAllWeapons(client);
Client_SetMaxSpeed(client, 400.0);

new DropRandom = GetRandomInt(0, 35);
GivePlayerItem(client, Weapon_names[DropRandom]);
CGOPrintToChatAll("%s {GRAY}выйграл %s! Попробуй и ты: !drop", DropWinner, Weapon_names[DropRandom]);
g_Drop--;
} else {
CGOPrintToChat(client, "{GRAY}Вы уже использовали {LIGHTOLIVE}!drop{GRAY} в этом раунде.");
}
} else {
CGOPrintToChat(client, "{GRAY}Вы не можете использовать {LIGHTOLIVE}!drop{GRAY}, если вы мертвы или в спектрах.");
}
return Plugin_Handled;
}
Для ограничения использования комманды я создал глобальную переменную g_Drop = 1, которая уменьшается на 1 при использовании команды и увеличивается на 1 при смерти.
Но поскольку переменная глобальная и не привязана ни к чему, при использовании команды одним игроком, она, видимо, уменьшается и препятствует использованию другими игроками. На деле команда вообще никогда не работает, поскольку не выполняется условие g_Drop == 1.

Дайте совет, как разделить переменную для каждого игрока(полный ноль на самом деле в этом), и прочие советы по реализации плагина. Заранее благодарю.
 

Вложения

  • drop.sp
    1.9 КБ · Просмотры: 25
Последнее редактирование:

FrozDark

Участник
Сообщения
1,769
Реакции
2,050
прикрепляйте наброски к сообщениям в формате sp
 

diller110

Добрая душа
Сообщения
353
Реакции
278
Т.е. мы создаем массив из Maxplayers игроков. Определяем все значения начальными 1-ами:
new g_Drop[MAXPLAYERS+1] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1} Если на сервере например 10 максимум.
Значит визуально массив выглядит так:
g_Drop[0] = 1;
g_Drop[1] = 1;
g_Drop[n] = 1;....

Тогда какое значение в [] подставлять для его изменения например в Event_PlayerDeath?
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
diller110, основу сделал ниже на примере с bool. Т.е. работает 1 раз за 1 жизнь:
PHP:
#include <sourcemod>
#include <sdktools>
#include <csgo_colors>
#include <smlib>

new const String:Weapon_names[36] [] = {
	"weapon_ak47", "weapon_aug", "weapon_bizon", "weapon_deagle", "weapon_decoy", "weapon_elite", "weapon_famas", "weapon_fiveseven", "weapon_flashbang",
	"weapon_g3sg1", "weapon_galilar", "weapon_glock", "weapon_hegrenade", "weapon_hkp2000", "weapon_incgrenade", "weapon_knife", "weapon_m249", "weapon_m4a1",
	"weapon_mac10", "weapon_mag7", "weapon_molotov", "weapon_mp7", "weapon_mp9", "weapon_negev", "weapon_nova", "weapon_p250", "weapon_p90", "weapon_sawedoff",
	"weapon_scar20", "weapon_sg556", "weapon_smokegrenade", "weapon_ssg08", "weapon_taser", "weapon_tec9", "weapon_ump45", "weapon_xm1014"
};
new bool:g_Drop[MAXPLAYERS+1];

public Plugin:myinfo =
{
	name = "Drop",
}

public OnPluginStart()
{
	RegConsoleCmd("sm_drop", Command_DropJoke, "Joke with Drop command");
	HookEvent("player_death", Event_PlayerDeath);
}
public Action:Command_DropJoke(client, args)
{
	if (client)
	{
		if (IsPlayerAlive(client))
		{
			if (g_Drop[client]) CGOPrintToChat(client, "{GRAY}Вы уже использовали {LIGHTOLIVE}!drop{GRAY} в этом раунде.");
			else
			{
				g_Drop[client] = true;
				decl String:DropWinner[MAX_NAME_LENGTH];
				GetClientName(client, DropWinner, MAX_NAME_LENGTH);
				Client_RemoveAllWeapons(client);
				Client_SetMaxSpeed(client, 400.0);
				
				new DropRandom = GetRandomInt(0, 35);
				GivePlayerItem(client, Weapon_names[DropRandom]);
				CGOPrintToChatAll("%s {GRAY}выйграл %s! Попробуй и ты: !drop", DropWinner, Weapon_names[DropRandom]);
			}
		}
		else CGOPrintToChat(client, "{GRAY}Вы не можете использовать {LIGHTOLIVE}!drop{GRAY}, если вы мертвы или в спектрах.");
	}
	return Plugin_Handled; 
}
public Event_PlayerDeath(Handle:event, String:name[], bool:dontBroadcast) g_Drop[GetClientOfUserId(GetEventInt(E, "userid"))] = false;
 

diller110

Добрая душа
Сообщения
353
Реакции
278
Спасибо за советы! На самом деле я тоже сделал только основу, первый плагин, коплю опыт. Вопросов попутно только больше...

В основном Actione проиндексировал g_Drop по примеру из PlayerDeath:
g_Drop[GetClientOfUserId(GetEventInt(Event_PlayerDeath, "userid"))
Все хорошо только несоответствие tag выдает, как предупреждение(warning 213). Наверно не страшно, но интересно как исправить.

Еще вопрос, значение decl String:DropWinner[MAX_NAME_LENGTH]; "задекларировали", для чего это нужно?

И еще вопрос, if (client) {..} как понимаю это защита от ввода команды с сервера?

И еще вопросик, sm_drop стандартная sm команда, которая кидает вещи, причем странным образом. При вводе команды уже с моим плагином, она конечно выполняется, но в чат помимо моего вводится мол вы ввели команду не корректно, правильно sm_drop target weapon, можно ли скрыть это сообщение, или вообще заблокировать стандартное выполнение. Не очень надо конечно, но интересно.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
несоответствие tag выдает, как предупреждение(warning 213)
Создан массив bool переменных, а ты, видимо, пытаешься править в int. Убери bool: в самом начале.
"задекларировали", для чего это нужно?
Выше скорость, короче говоря. Меньше задержка для создания массива.
защита от ввода команды с сервера?
Да.
 

diller110

Добрая душа
Сообщения
353
Реакции
278
bool убрал, ошибка оставалась, добавил к GetEventInt(Event_PlayerDeath, "userid")
Handle: перед Event_PlayerDeath, ошибка исчезла, хотя объяснить почему не смогу.
Спасибо, очень познавательный урок!)
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755

diller110

Добрая душа
Сообщения
353
Реакции
278
Еще нужна помощь. Как лучше реализовать выдачу оружия. Первый раз была отчистка всего инвертаря с помощью smlib функции Client_RemoveAllWeapons(client, "weapon_c4"); (все кроме бомбы), а потом выдача ножа - GivePlayerItem(client, Weapon_names[15]); и уже рандомного оружия.

Но возникает ощущение незаконченности и вообще недоделки, т.к. при дропе удаляется все оружие, было ли у вас AWP, или просто глок.

Как лучше реализовать выдачу? В smlib есть несколько функций например: Client_EquipWeapon(client, weapon) и Client_GiveWeapon(client, className[]). В первом случае нужен weapon - Entity index of the weapon, в втором className[] - weapon classname string. В обоих случаях не знаю где эти значения взять.

____
Вообще проблема с Entity. Кусок кода, который я любезно одолжил не помню откуда:
new const String:Weapon_names[36] [] = {
"weapon_ak47", "weapon_aug", "weapon_bizon", .... Дает нам Weapon_Names(Source), это уже Entity?, если да то как получить их Index?
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
В обоих случаях не знаю где эти значения взять
GivePlayerItem - нужен classname (название) оружия. Берём просто из составленного тобой списка выдаваемого оружия текущее оружие и всё - никаких smlib не требуется! Так в чём же состоит задача? Узнать, какое оружие в руках у игрока или вообще какое он с собой носит (в слотах)?
 

diller110

Добрая душа
Сообщения
353
Реакции
278
Так в чём же состоит задача? Узнать, какое оружие в руках у игрока или вообще какое он с собой носит (в слотах)?

GivePlayerItem как я понимаю просто кидает предмет под игрока, и игрок его берет, если у него свободны слот. Если нет оружие просто падает под ноги. Я бы хотел, чтобы оружие в рука заменялось оружием дропа.
Как вариант, в массиве найти все строки с основным оружием и вторичным, и для каждого условие сделать типо сначала удалить оружие для этого слота потом выкинуть.
Но как-то такое решение в лоб не красиво выглядит.
EquipPlayerWeapon - думаю подошел бы, однако незнаю как получить для него аргумент
weapon - CBaseCombatWeapon entity index.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
просто кидает предмет под игрока, и игрок его берет
Нет, не кидает, если слот даваемого оружия пустой.
Я бы хотел, чтобы оружие в рука заменялось оружием дропа
Тогда узнаём оружие игрока в нужном слоте (основное/вторичное), удаляем и GivePlayerItem - если основное, то оно уже будет в руках, а если вторичное - появится сразу после переключения на него. Под ногами ничего не будет. Только дефуз так выдаётся, а оружие - нет.
Написал бы теперь пример, да боюсь, без встраивания в твой код опять возникнут вопросы.
 

TolikCorp

Участник
Сообщения
874
Реакции
334
Кстати, лучше на спавне изменять значение g_Drop[бла бла] = false;
 

diller110

Добрая душа
Сообщения
353
Реакции
278
Кстати, лучше на спавне изменять значение g_Drop[бла бла] = false;
Да спасибо за совет. Только поставил на начало раунда.

Нет, не кидает, если слот даваемого оружия пустой.
Дела обстоят так. Команда GivePlayerItem(client, Weapon_names[DropRandom]);
Предмет кидается в мир под игрока, если слот пустой он разумеется его берет. Если например с прошлого раунда оружие осталось, то предмет падает под ноги. Я бы хотел сделать замену предмета из инвертаря на предмет рандома.

Как получить информацию об определенном слоте оружия? Я попробывал вот так: (С помощью smlib)
new Primary = Client_GetWeaponBySlot(client, 1);
new Secondary = Client_GetWeaponBySlot(client, 2);
CGOPrintToChat(client, "Индекс вашего первого оружия: %d. Индекс второго: %d.", Primary, Secondary);

_____________
После некоторых манипуляция получилось получить, то что я хотел.
GetEntityClassname(Client_GetWeaponBySlot(client, slot);
где слот: 0 - основное оружие, 1 - пистолеты, 2 - нож.

Осталось сделать условия для определенных id из массива с названиями оружия. Хотя уверен есть способы сделать все более просто.

Есть способ получить тип предмета? Например weapon_ak47 - primary_weapon,
weapon_p2000 - pistol, weapon_knife - knife.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
diller110, так можно:
PHP:
#include <cstrike>
#include <sdktools_functions>
#include <sdktools_entinput>


new Primary = GetPlayerWeaponSlot(client, CS_SLOT_PRIMARY);
if (Primary != -1)
{
	//RemovePlayerItem(client, Primary);
	AcceptEntityInput(Primary, "Kill");
	CGOPrintToChat(client, "В 1 слоте находилось оружие с индексом %i.", Primary);
}
else
{
	CGOPrintToChat(client, "Ваш слот первичного оружия пуст!");
}
if (GivePlayerItem(client, Weapon_names[DropRandom]) != -1)
{
	CGOPrintToChat(client, "У вас %sбыло оружия! Вам было выдано: %s.", Primary != -1 ? "":"НЕ ", Weapon_names[DropRandom]);
}
else
{
	CGOPrintToChat(client, "Не удалось выдать оружие: %s (не существует в текущей игре!).", Weapon_names[DropRandom]);
}
Так же и с вторичным оружием, только слот меняешь (CS_SLOT_PRIMARY на CS_SLOT_SECONDARY).
 
Последнее редактирование:

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #17
AlmazON, слоты:
0 - основное (автоматы, снайперки),
1 - вторичное (пистолеты)
2 - нож
3- гранаты
4 - с4
 

TolikCorp

Участник
Сообщения
874
Реакции
334
Выдержка из cstrike.inc:
PHP:
#define CS_SLOT_PRIMARY		0	/**< Primary weapon slot. */
#define CS_SLOT_SECONDARY	1	/**< Secondary weapon slot. */
#define CS_SLOT_KNIFE		2	/**< Knife slot. */
#define CS_SLOT_GRENADE		3	/**< Grenade slot (will only return one grenade). */
#define CS_SLOT_C4			4	/**< C4 slot. */

Тем более, что уже подключено: #include <cstrike>
 

diller110

Добрая душа
Сообщения
353
Реакции
278
Всем спасибо! Теперь все работает так, как должно работать)

Выдержка из cstrike.inc

А есть еще что-нибудь в документации по поводу classname или к чему принадлежат названия типа: weapon_awp, weapon_knife.
А то сейчас вывожу в чат оружие которым убили и помимо стандартных из: https://wiki.alliedmods.net/Counter-Strike:_Global_Offensive_Weapons , например вместо weapon_m4a1 выводит weapon_m4a1_silenced, вместо weapon_knife - knife_butterfly(из плагина knife choise). Где можно увидеть полный список подобных названий?
 
Последнее редактирование:

TolikCorp

Участник
Сообщения
874
Реакции
334
Лучше пролистай все стандартные инклуды.
Учись по примерам, открой тот же WeaponRestrict - там гигантское множество трюков с пушками, логики и прочего.
 
Сверху Снизу