Если есть опыт, то можете ознакомиться с форумом пользователя wS, там много ценной информации. Или заказать плагин у скриптеров.Нужен плагин который будет очищать первый и второй слоты после победы одной из команд, т.е. в конце раунда [AWP и DEAGLE]
new weapon = GetPlayerWeaponSlot(client, 0);
if (weapon > MaxClients) CS_DropWeapon(client, weapon, true, false);
new weapon = GetPlayerWeaponSlot(client, 0);
if (weapon > MaxClients) RemovePlayerItem(client, weapon)
@Max Rhine, мне кажется я что то делаю не так :/
#include <sourcemod>
public void OnPluginStart()
{
HookEvent("round_end", Event_RoundEnd);
}
public Action Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
{
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientInGame(i))
{
int client = i;
ClientCommand(client, "strip");
}
}
return Plugin_Handled;
}
#include <cstrike>
#include <sdktools_entinput>
#include <sdktools_functions>
enum
{
Slot_Primary = 0,
Slot_Secondary,
Slot_Knife,
Slot_Grenade,
Slot_C4,
Slot_None
};
public void OnPluginStart()
{
HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
}
public void Event_RoundEnd(Event event, const char[] name, bool dontBroadcast)
{
for(int i = 1, j, wpn; i <= MaxClients; ++i) if(IsClientInGame(i) && IsPlayerAlive(i))
{
for(j = Slot_Primary; j < Slot_None; j++)
{
while((wpn = GetPlayerWeaponSlot(i, j)) != -1)
{
if(RemovePlayerItem(i, wpn))
{
#if SOURCEMOD_V_MAJOR < 2 && SOURCEMOD_V_MINOR < 10
AcceptEntityInput(wpn, "Kill");
#else
RemoveEntity(wpn);
#endif
}
}
}
GivePlayerItem(i, "weapon_knife");
}
}
А это нафига?C-подобный:int client = i; ClientCommand(client, "strip");
ClientCommand(i, "strip");
не угодил1. А IsClientSourceTV может быть жив? Если нет, то зачем проверять его вообще?Всё ж намного проще... без лишнего кода и мусора
#include <sdktools>
public Plugin myinfo =
{
name = "RemoveWeapons",
author = "MaxRhine",
version = "16.09.2023",
url = "https://t.me/maxongg"
};
public void OnPluginStart()
{
HookEvent("round_end", Event_RoundEnd);
}
public Action:Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast)
{
new client = GetClientOfUserId(GetEventInt(event, "userid"));
if (IsClientInGame(client) && !IsClientSourceTV(client) && IsPlayerAlive(client))
{
for (int i = 0; i <= 4; i++)
{
RemovePlayerItem(client, GetPlayerWeaponSlot(client, i)!= -1);
GivePlayerItem(client, "weapon_knife");
}
}
}
#include <sdktools_functions>
public void OnPluginStart()
{
HookEvent("round_end", Event_RoundEnd);
}
void Event_RoundEnd(Event hEvent, const char[] name, bool dontBroadcast)
{
for(int i = 1; i <= MaxClients; i++) if(IsClientInGame(i) && IsPlayerAlive(i))
{
for (int j; j < 5; j++) if(j != 2 && GetPlayerWeaponSlot(i, j) != -1)
{
RemovePlayerItem(i, j);
}
}
}
public в ивенте забыл, он должен быть1. А IsClientSourceTV может быть жив? Если нет, то зачем проверять его вообще?
2. А разве в событие конца раунда, есть этот эвент?
GetClientOfUserId(GetEventInt(event, "userid"));
3. Смесь старого и нового синтаксиса
public void OnPluginStart()
против
public Action:Event_RoundEnd
4. А если
GetClientOfUserId(GetEventInt(event, "userid"))
То это не означает что игрок точно онлайн ? Зачем тогда проверка IsClientInGame
C++:#include <sdktools> public Plugin myinfo = { name = "RemoveWeapons", author = "MaxRhine", version = "16.09.2023", url = "https://t.me/maxongg" }; public void OnPluginStart() { HookEvent("round_end", Event_RoundEnd); } public Action:Event_RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) { new client = GetClientOfUserId(GetEventInt(event, "userid")); if (IsClientInGame(client) && !IsClientSourceTV(client) && IsPlayerAlive(client)) { for (int i = 0; i <= 4; i++) { RemovePlayerItem(client, GetPlayerWeaponSlot(client, i)!= -1); GivePlayerItem(client, "weapon_knife"); } } }
Сообщения автоматически склеены:
Тогда уж как то так
C++:#include <sdktools_functions> public void OnPluginStart() { HookEvent("round_end", Event_RoundEnd); } void Event_RoundEnd(Event hEvent, const char[] name, bool dontBroadcast) { for(int i = 1; i <= MaxClients; i++) if(IsClientInGame(i) && IsPlayerAlive(i)) { for (int j; j < 5; j++) if(j != 2 && GetPlayerWeaponSlot(i, j) != -1) { RemovePlayerItem(i, j); } } }
Последнее время всегда без них делаю, всё в порядкеpublic в ивенте забыл, он должен быть
Ну давай разберём твой код:без лишнего кода и мусора
public Action:Event_RoundEnd()
public Event_RoundEnd()
в случае старого синтаксиса или public void Event_RoundEnd()
в случае нового. Поэтому ещё можно в строке 14 добавить флаг EventHookMode_PostNoCopy
, говорящий соурсмоду, что мы не планируем получать никакие данные от хука события.new client = GetClientOfUserId(GetEventInt(event, "userid"));
if (IsClientInGame(client) && !IsClientSourceTV(client) && IsPlayerAlive(client))
При всём при этом у нас client равен 0, а проверки валидности индекса (должен быть больше 0) я тут не вижу.GetClientTeam(client) > 1
for (int i = 0; i <= 4; i++)
Тут всё нормально (точно так же как у меня проверяются все 5 слотов), но int i = 0;
делать не обязательно: достаточно просто int i;
, т.к. в SM (как минимум в 1.6 уже было) присваивает переменным при создании значение равное нулю (для любых типов; у float - 0.0, у Handle - INVALID_HANDLE и т.д.).GivePlayerItem(client, "weapon_knife");
на кой в каждой итерации цикла прохода по слотам выдавать нож ума не приложу. В лучшем случае у игрока после такого будет под ногами валяться 5 ножей. Эта строка должна выполняться после завершения цикла.#include <sdktools>
написать #include <sdktools_functions>
, т.к. нам не нужны все прочие функции, содержащиеся в остальных инклюдах SDKTools.//// clean sdktools_functions.sp
//
// Code size: 3968 bytes
// Data size: 2404 bytes
// Stack/heap size: 16468 bytes
// Total requirements: 22840 bytes
//
// Compilation Time: 0,23 sec
// ----------------------------------------
//// clean sdktools.sp
//
// Code size: 3968 bytes
// Data size: 2448 bytes
// Stack/heap size: 16468 bytes
// Total requirements: 22884 bytes
//
// Compilation Time: 0,27 sec
// ----------------------------------------
Писал по сути на ксс, но учту этот момент в будущем.А в CS:GO добавилось оружие помимо гранат, которое может находится в одном и том же слоте.
Это понял уже, как и 5-й пункт)Т.е. дальше код в хуке события просто не будет выполняться
Дело привычки, как мне кажется и не имеет смысла. Ради пары байтов... в ущерб удобству. Тогда уж можно создать кастомный inc, убрав все ненужные функции. Или лучше использовать нативы напрямую с этих же inc, вместо #include <sdktools_functions>?))Ещё можно вместо#include <sdktools>
написать#include <sdktools_functions>
, т.к. нам не нужны все прочие функции, содержащиеся в остальных инклюдах SDKTools.
И ещё за счет этого скомпиленный плагин будет меньше:
Ну серьёзно.. мою невнимательность все заметили.#include <cstrike> #include <sdktools_entinput> #include <sdktools_functions>
Всё тот же нерабочий кусокТогда уж как то так
Компилятор просто записывает в тело плагина все перечисленные инклюды (инклюд sourcemod дописывается автоматически независимо от того указан ли он в исходнике).Или лучше использовать нативы напрямую с этих же inc, вместо #include <sdktools_functions>?
Если почитать AM и HLMod можно много чего узнать. В справочнике по API соурсмода (новый, старый синтаксисы) или прямо в файлах инклюдов тоже есть много информации.Кое-что новое таки узнал.
for(j = Slot_Primary; j < Slot_None; j++)
for(j = Slot_Primary; j < Slot_None; j++) if(j != Slot_Knife)
(и удалить строку 38 с выдачей ножа)Когда-то пытался учиться по справочнику. Это было интересно и в то же время непонятно