Как узнать находится ли игрок на лестнице
| |
Sunday
|
Дата: Пятница, 25.01.2013, 00:14:12 | Сообщение # 1 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
Парни, подскажите, возможно ли отловить событие когда игрок находится на лестнице и к примеру убить его? Дело в том что у меня один из серверов крутит одну карту и иногда некоторые игроки из команды висят на лестнице не давая другим подняться, когда нет админа на сервере, это сильно раздражает игроков. Вот я и подумал, может есть возможность как то это отловить и если игрок висит например больше 10 секунд то его убивает.
|
|
| |
_wS_
|
Дата: Пятница, 25.01.2013, 00:30:12 | Сообщение # 2 |
|
Код if (GetEntityMoveType(client) == MOVETYPE_LADDER) { // Игрок на лестнице } Наверно, придется проверять это условие каждые 'x' сек (CreateTimer). Есть еще более сложный и неудобный вариант с env_player_surface_trigger (OnSurfaceChangedToTarget, OnSurfaceChangedFromTarget), который позволяет ловить момент, когда игрок, например, переходит с бетона на дерево - только неизвестно, какой именно игрок, и можно ли поймать этот момент с лестницей.
|
|
| |
Sunday
|
Дата: Пятница, 25.01.2013, 05:31:36 | Сообщение # 3 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
Спасибо _wS_ за пример и подсказку, я сделал два варианта, если не затруднит, подскажите все ли верно и какой вариант будет менее нагружать сервер, меня очень сильно именно нагрузка на сервер волнует.
Вариант 1: Код #include <sourcemod>
public OnMapStart() { CreateTimer(10.0, t_timer, INVALID_HANDLE, TIMER_REPEAT); }
public Action:t_timer(Handle:timer) { for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { CreateTimer(10.0, t_PlayerKick, INVALID_HANDLE, TIMER_REPEAT); PrintToChat(client, "1"); } } }
return Plugin_Continue; }
public Action:t_PlayerKick(Handle:timer) { for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { KickClient(client); } } }
return Plugin_Stop; }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; }
Вариант 2: Код #include <sourcemod>
new Handle:t_timer[MAXPLAYERS+1];
public OnGameFrame() { for (new client=1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { t_timer [client]= CreateTimer(10.0, t_PlayerKick, client); } } } }
public Action:t_PlayerKick(Handle:timer, any:client) { t_timer [client]= INVALID_HANDLE;
if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { KickClient(client); } }
return Plugin_Stop; }
public OnClientDisconnect(client) { if (t_timer [client]!= INVALID_HANDLE) { KillTimer(t_timer[client]); t_timer [client]= INVALID_HANDLE; } }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; }
Добавлено (25.01.2013, 05:31:36) --------------------------------------------- еще хотел узнать, как убить игрока? Получается только кикнуть, я пытался сделать через: new String:clientname[255]; GetClientName(clientname, sizeof(clientname) а дальше ступор. Если не затруднит, подскажите.
Сообщение отредактировал Sunday - Пятница, 25.01.2013, 05:51:38 |
|
| |
scorpion2904
|
Дата: Пятница, 25.01.2013, 09:55:47 | Сообщение # 4 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
Убить с помощью ForcePlayerSuicide(client); , но тогда нужно еще подключить sdktools_functions (#include <sdktools_functions>)Добавлено (25.01.2013, 09:50:36) --------------------------------------------- Попробуй еще такой вариант :
Код #include <sourcemod> #include <sdktools> #include <sdktools_functions>
new Handle:Timer[MAXPLAYERS+1];
public OnPluginStart(){ HookEvent("round_start", round_start) }
public round_start(Handle:event, const String:name[], bool:dontBroadcast) { new index = -1; while ((index = FindEntityByClassname(index, "func_ladder")) > 0 || (index = FindEntityByClassname(index, "func_ladderendpoint") > 0)) { HookSingleEntityOutput(index, "OnStartTouch", OnStartTouch); HookSingleEntityOutput(index, "OnEndTouch", OnEndTouch); } }
public OnStartTouch(const String:output[], ent, client, Float:delay) { if (0 < client <= MaxClients && Timer [client]== INVALID_HANDLE) { Timer [client]= CreateTimer(10.0, TimerFunc, client, TIMER_REPEAT); } }
public OnEndTouch(const String:output[], ent, client, Float:delay) StopTimer(client); public OnClientDisconnect(client) StopTimer(client);
StopTimer(client) { if (Timer [client]!= INVALID_HANDLE) { KillTimer(Timer[client]); Timer [client]= INVALID_HANDLE; } }
public Action:TimerFunc(Handle:timer, any:client) { ForcePlayerSuicide(client); Timer [client]= INVALID_HANDLE; return Plugin_Stop; } Добавлено (25.01.2013, 09:55:47) --------------------------------------------- Если из твоих выбирать, то первый лучше. Только по-моему во всех случаях будет убивать и того кто стоит на лестнице и того кто не может из-за первого пройти
|
|
| |
Sunday
|
Дата: Пятница, 25.01.2013, 12:47:06 | Сообщение # 5 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
scorpion2904 да, ведь на самом деле Вы правильно говорите, убивать будет обоих... А я и не подумал о таких важных моментах . Спасибо Вас большое, скрипт попробовал, идея хорошая но непонятно по каким причинам РаундСтарт не работает! Я попробовал в каждую функцию поставить PrintToChatAll("1") что бы проверить что активируется но ни одного сообщения не получил.
|
|
| |
scorpion2904
|
Дата: Пятница, 25.01.2013, 16:34:28 | Сообщение # 6 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
То есть даже
Код public round_start(Handle:event, const String:name[], bool:dontBroadcast) { PrintToChatAll("1") }
не работает?Добавлено (25.01.2013, 16:34:28) --------------------------------------------- Может быть сделать так, чтобы когда игрок находится на лестнице через него можно было пройти? SetEntProp(client, Prop_Data, "m_CollisionGroup", 2);
|
|
| |
Sunday
|
Дата: Суббота, 26.01.2013, 05:17:23 | Сообщение # 7 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
Цитата (scorpion2904) То есть даже
Код public round_start(Handle:event, const String:name[], bool:dontBroadcast) { PrintToChatAll("1") }
не работает?
да, не работает, я ни когда раунд старт не использовал, может быть надо брать индекс игрока в качестве эвента, может по этому не работает.
*** Цитата (scorpion2904) Может быть сделать так, чтобы когда игрок находится на лестнице через него можно было пройти? SetEntProp(client, Prop_Data, "m_CollisionGroup", 2);
Ваша идея Великолепна! Ведь это на много лучше, спасибо за идею я именно так и буду делать, это ни кого не обидит и все довольны Добавлено (26.01.2013, 05:17:23) --------------------------------------------- Вот что получилось:
Код #include <sourcemod> #pragma semicolon 1
new Handle:h_Timer[MAXPLAYERS+1];
public OnMapStart() { CreateTimer(10.0, t_timer, INVALID_HANDLE, TIMER_REPEAT); }
public Action:t_timer(Handle:timer) { for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client) && h_Timer[client] == INVALID_HANDLE) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { h_Timer[client] = CreateTimer(10.0, t_LadderNoclip, client); } } } return Plugin_Continue; }
public Action:t_LadderNoclip(Handle:timer, any:client) { h_Timer[client] = INVALID_HANDLE; if (!IsClientInGame(client)) return Plugin_Stop;
if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { SetEntProp(client, Prop_Data, "m_CollisionGroup", 2); } else { SetEntProp(client, Prop_Data, "m_CollisionGroup", 0); } } return Plugin_Stop; }
public OnClientDisconnect(client) { if (h_Timer[client] != INVALID_HANDLE) { KillTimer(h_Timer[client]); h_Timer[client] = INVALID_HANDLE; } }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; }
Все работает, буду признателен если укажите на ошибки, если они имеются. Хотелось бы добавить третью функцию, если запущен таймер и игрок уже не на лестнице, то таймер убивался, что то не пойму как это сделать с этими иф и элсе...
Сообщение отредактировал Sunday - Пятница, 25.01.2013, 21:45:03 |
|
| |
scorpion2904
|
Дата: Суббота, 26.01.2013, 09:50:09 | Сообщение # 8 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
В Вашем коде ошибок я не увидел, но есть ли смысл создавать таймер на игрока, если можно сразу дать ему ноу блок.
Код #include <sourcemod> #pragma semicolon 1
public OnMapStart() { CreateTimer(10.0, t_timer, INVALID_HANDLE, TIMER_REPEAT); }
public Action:t_timer(Handle:timer) { for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { SetEntProp(client, Prop_Data, "m_CollisionGroup", 2); } else{ SetEntProp(client, Prop_Data, "m_CollisionGroup", 0); } } } return Plugin_Continue; }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; } Хотя по-моему мой вариант будет меньше нагружать сервер т.к. там можно обойтись без таймеров.Вы для Counter-Strike:Source делаете этот плагин?
|
|
| |
Sunday
|
Дата: Суббота, 26.01.2013, 20:50:32 | Сообщение # 9 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
Цитата (scorpion2904) В Вашем коде ошибок я не увидел, но есть ли смысл создавать таймер на игрока, если можно сразу дать ему ноу блок.
Код #include <sourcemod> #pragma semicolon 1
public OnMapStart() { CreateTimer(10.0, t_timer, INVALID_HANDLE, TIMER_REPEAT); }
public Action:t_timer(Handle:timer) { for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) { SetEntProp(client, Prop_Data, "m_CollisionGroup", 2); } else{ SetEntProp(client, Prop_Data, "m_CollisionGroup", 0); } } } return Plugin_Continue; }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; }
Цитата (scorpion2904) Хотя по-моему мой вариант будет меньше нагружать сервер т.к. там можно обойтись без таймеров.Вы для Counter-Strike:Source делаете этот плагин?
Спасибо scorpion2904, Вы в очередной раз оказались правы! Сейчас когда выспался хорошо, смотрю и думаю, а на самом деле зачем я создавал второй таймер . Еще раз спасибо scorpion2904 за поддержку и отличные идеи!
п.с. Плагин для half-life 2 Deathmatch, там есть популярная карта "РунОфф" и иногда на ней бывает, когда одна команда проигрывает, некоторые ... игроки переходят в другую команду и перекрывают проход на лестнице не давая пройти к основному оружию ну и собственно команда начинает проигрывать.
Добавлено (26.01.2013, 15:10:53) --------------------------------------------- http://world-source.ru/forum/129-3072-1Добавлено (26.01.2013, 20:50:32) --------------------------------------------- эх, почему из за m_CollisionGroup бывает сбой на карте и все предметы падают под карту... В чем может быть проблема парни?
Сообщение отредактировал Sunday - Суббота, 26.01.2013, 15:11:40 |
|
| |
scorpion2904
|
Дата: Суббота, 26.01.2013, 20:57:56 | Сообщение # 10 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
Всмысле сами игроки падают под карту?
|
|
| |
scorpion2904
|
Дата: Суббота, 26.01.2013, 21:11:31 | Сообщение # 11 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
Попробуй так еще:
Код #include <sourcemod> #include <sdktools>
public OnPluginStart() HookEvent("teamplay_round_start", round_start)
public round_start(Handle:event, const String:name[], bool:dontBroadcast) { new index = -1; while ((index = FindEntityByClassname(index, "func_ladder") > 0) || (index = FindEntityByClassname(index, "func_ladderendpoint")) > 0 || (index = FindEntityByClassname(index, "func_useableladder") > 0)) { HookSingleEntityOutput(index, "OnStartTouch", OnStartTouch); HookSingleEntityOutput(index, "OnEndTouch", OnEndTouch); } }
public OnStartTouch(const String:output[], ent, client, Float:delay) SetEntProp(client, Prop_Data, "m_CollisionGroup", 2);
public OnEndTouch(const String:output[], ent, client, Float:delay) SetEntProp(client, Prop_Data, "m_CollisionGroup", 0); Для half-life 2 Deathmatch должно работать.Может быть, так этого бага не будет.
Гости не могут скачивать файлы
|
|
|
| |
Sunday
|
Дата: Суббота, 26.01.2013, 21:22:07 | Сообщение # 12 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
Цитата (scorpion2904) Всмысле сами игроки падают под карту?
Предметы, вот и гадаю из за чего функция которая в обще не относится к предметам, влияет на них. Я ни раз замечал такой баг, с плагинами которые дают ноклип. Возможно это как то только в Халфлайф влияет.
И еще я вспомнил для чего я делал втротой таймер))))))) Для того что бы в момент проверки игрока сразу не кикнуло, первый таймер запускает проверку а второй время допустимое на лестнице и как я мог забыть. Так что надо будет его добавить, а то получается если игрок попадает в момент проверки но он сам находился на лестнице менее 10 секунд то он все равно кикается...
Спасибо scorpion2904, сейчас попробую! ************************************ Так тоже 0 эмоций.
Сообщение отредактировал Sunday - Суббота, 26.01.2013, 21:28:14 |
|
| |
scorpion2904
|
Дата: Суббота, 26.01.2013, 21:32:57 | Сообщение # 13 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
Тогда наверное лучше будет оставить твой вариант только вместо кика убивать (ForcePlayerSuicide(client);). Хотя щас еще попробую что-нибудь придуматьДобавлено (26.01.2013, 21:32:57) --------------------------------------------- Ты начала раунда дождался при последнем тесте?
|
|
| |
Sunday
|
Дата: Суббота, 26.01.2013, 21:54:26 | Сообщение # 14 |
|
Сообщений: 186
Репутация: 24 [ +/- ]
|
|
Цитата (scorpion2904) Ты начала раунда дождался при последнем тесте?
Да, в Халфлайф начало раунда сразу, то есть нет закупок и тому подобное как в контр страйк, там сразу как игрок появился или отреспамился или как зашел в игру то это уже и есть начало раунда. В принципе работает отлично, хотелось бы конечно не кикать а убивать игрока, не понятно из за чего не получается так сделать, сейчас буду штрудировать примеры, смотреть как и где это реализовано!
Вот что получилось: (осталось только понять как сделат не кик а килл)
Код #include <sourcemod> #pragma semicolon 1
public Plugin:myinfo = { name = " [ASP]Ladder Nonblocking for DM RunOFF, (ver. 1.0.0 beta)", author = "Aurora [Russia], scorpion2904, _wS_", description = "NoBlock на лестнице", url = "http://world-source.ru" };
new Handle:hTimer[MAXPLAYERS+1];
public OnMapStart() CreateTimer(10.0, t_timer, INVALID_HANDLE, TIMER_REPEAT);
public Action:t_timer(Handle:timer) {
for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client) && hTimer [client]== INVALID_HANDLE) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) hTimer [client]= CreateTimer(10.0, aTimer, client); PrintToChatAll("На лестнице?"); } } return Plugin_Continue; }
public Action:aTimer(Handle:timer, any:client) {
hTimer [client]= INVALID_HANDLE;
if (!IsClientInGame(client)) return Plugin_Stop;
if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) KickClient(client, "Вы Кикнуты за блокировку лестници!"); }
return Plugin_Stop; }
public OnClientDisconnect(client) { if (hTimer [client]!= INVALID_HANDLE) { KillTimer(hTimer[client]); hTimer [client]= INVALID_HANDLE; } }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; }
Гости не могут скачивать файлы
|
Сообщение отредактировал Sunday - Суббота, 26.01.2013, 21:57:41 |
|
| |
scorpion2904
|
Дата: Суббота, 26.01.2013, 22:04:27 | Сообщение # 15 |
|
Сообщений: 68
Репутация: 5 [ +/- ]
|
|
Код #include <sourcemod> #include <sdktools> #include <sdktools_functions> #pragma semicolon 1
public Plugin:myinfo = { name = " [ASP]Ladder Nonblocking for DM RunOFF, (ver. 1.0.0 beta)", author = "Aurora [Russia], scorpion2904, _wS_", description = "NoBlock на лестнице", url = "http://world-source.ru" };
new Handle:hTimer[MAXPLAYERS+1];
public OnMapStart() CreateTimer(10.0, t_timer, INVALID_HANDLE, TIMER_REPEAT);
public Action:t_timer(Handle:timer) {
for (new client = 1; client <= MaxClients; client++) { if (IsValidClient(client) && IsPlayerAlive(client) && hTimer [client]== INVALID_HANDLE) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) hTimer [client]= CreateTimer(10.0, aTimer, client); PrintToChatAll("На лестнице?"); } } return Plugin_Continue; }
public Action:aTimer(Handle:timer, any:client) {
hTimer [client]= INVALID_HANDLE;
if (!IsClientInGame(client)) return Plugin_Stop;
if (IsValidClient(client) && IsPlayerAlive(client)) { if (GetEntityMoveType(client) == MOVETYPE_LADDER) ForcePlayerSuicide(client); }
return Plugin_Stop; }
public OnClientDisconnect(client) { if (hTimer [client]!= INVALID_HANDLE) { KillTimer(hTimer[client]); hTimer [client]= INVALID_HANDLE; } }
stock IsValidClient(client) { if(IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) return true; return false; } Так должно убивать.В zombie panic у меня так работало.
|
|
| |
|