Поджигание - смерть - фраг

iamdss

Участник
Сообщения
126
Реакции
12
По просьбам игроков добавил к стрелам, выпущенным из арбалета, пламя. Использовал штатную функцию SM. Стрелы горят, воткнувшиеся стрелы наносят урон огнём, а при попадании по игрокам - поджигают их:

C-подобный:
public OnPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
	if (IsValidClient(client) && IsValidClient(attacker))
	{
		decl String:AllWeapon[20];
		GetClientWeapon(attacker, AllWeapon, 20);
		if (StrEqual("weapon_crossbow", AllWeapon, false))
		{
			IgniteEntity(client, 1.5);
		}
	}
}

Но если игрок не был добил атакующим, а умер от догорания, фраг атаковавшему не засчитывается, игрок совершает суицид. Как засчитать фраг тому, кто поджёг? И есть ли способы поджигания лучше штатной IgniteEntity?
 

gibs

Фитиль народного волненья
Сообщения
722
Реакции
407
Мошенник
env_fire . Если урон наносишь от этой ентити, то через сдк хукс заменяй атакующего.
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #4
iamdss, в SDKHooks в SDKHook_OnTakeDamage есть &iAttacker это значит что передается ссылка на оригинальное значение, тоесть прямая адресация. Просто делаешь iAttacker = iEntity.
Это если я верно понял.
Еще урон наносить можно так: https://sm.alliedmods.net/api/index.php?fastload=show&id=1028&
И так просто указываешь свою ентити
 

iamdss

Участник
Сообщения
126
Реакции
12
Дошли руки, вроде разобрался.

C-подобный:
public OnClientPutInServer(client)  
{
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

public Action:OnTakeDamage(client, &attacker, &inflictor, &Float:damage, &damagetype)  
{
	decl String:classname[64]; 
	GetEntityClassname(attacker, classname, sizeof(classname)); 
	if(StrEqual(classname, "entityflame", false))
	{
		inflictor = attacker;
		attacker = GetEntPropEnt(attacker, Prop_Send, "m_hOwnerEntity");
		return Plugin_Changed;
	}
	return Plugin_Continue;  
}

Надеюсь, всё верно. Как протестирую, отпишу.

Добавлено через 32 минуты
Проверил. Не срабатывает. Без изменений. Видимо, я неверно понял сей коллбек... Поправьте меня, кому не трудно.
 
Последнее редактирование:

gibs

Фитиль народного волненья
Сообщения
722
Реакции
407
Мошенник
Дошли руки, вроде разобрался.

C-подобный:
public OnClientPutInServer(client)  
{
	SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

public Action:OnTakeDamage(client, &attacker, &inflictor, &Float:damage, &damagetype)  
{
	decl String:classname[64]; 
	GetEntityClassname(attacker, classname, sizeof(classname)); 
	if(StrEqual(classname, "entityflame", false))
	{
		inflictor = attacker;
		attacker = GetEntPropEnt(attacker, Prop_Send, "m_hOwnerEntity");
		return Plugin_Changed;
	}
	return Plugin_Continue;  
}

Надеюсь, всё верно. Как протестирую, отпишу.

Добавлено через 32 минуты
Проверил. Не срабатывает. Без изменений. Видимо, я неверно понял сей коллбек... Поправьте меня, кому не трудно.

Убивай ентити огня не сразу, а через какое-то время. Вероятно. в логи сыпет ошибки, что ентити не валидная. Но а так, в принципе, правильно. Урон точно наносится от env_fire?
Нанесение урона обычно получается на следующем фрейме, так как сперва проходят всякие трассировки и прочее. Я так лично несколько раз заменял атакующего. К тому же, если взять параметры коллбека с вейпоном, то можно заменить сам вейпон, и в прэ хуке player_death заменять оружие для отображения нужной иконки в худе.
 

iamdss

Участник
Сообщения
126
Реакции
12
Убивай ентити огня не сразу, а через какое-то время.

Я использую стандартную SM функцию IgniteEntity с таймингом 1,5 секунды:

C-подобный:
public OnPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
	if (IsValidClient(client) && IsValidClient(attacker))
	{
		decl String:AllWeapon[20];
		GetClientWeapon(attacker, AllWeapon, 20);
		if (StrEqual("weapon_crossbow", AllWeapon, false))
		{
			IgniteEntity(client, 1.5);
		}
	}
}

Поэтому урон приходит от энтити класса entityflame и убивать вручную её не требуется. Нужно непременно воспользоваться env_fire?

Вероятно. в логи сыпет ошибки, что ентити не валидная.

Спасибо, действительно, ошибки. Поправил.

К тому же, если взять параметры коллбека с вейпоном, то можно заменить сам вейпон, и в прэ хуке player_death заменять оружие для отображения нужной иконки в худе.

Было бы отлично. Не найдётся куска кода? Обычно не прошу готовый, но это для меня пока китайская азбука.
 

gibs

Фитиль народного волненья
Сообщения
722
Реакции
407
Мошенник
Я использую стандартную SM функцию IgniteEntity с таймингом 1,5 секунды:

C-подобный:
public OnPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
	if (IsValidClient(client) && IsValidClient(attacker))
	{
		decl String:AllWeapon[20];
		GetClientWeapon(attacker, AllWeapon, 20);
		if (StrEqual("weapon_crossbow", AllWeapon, false))
		{
			IgniteEntity(client, 1.5);
		}
	}
}

Поэтому урон приходит от энтити класса entityflame и убивать вручную её не требуется. Нужно непременно воспользоваться env_fire?



Спасибо, действительно, ошибки. Поправил.



Было бы отлично. Не найдётся куска кода? Обычно не прошу готовый, но это для меня пока китайская азбука.

Если ты используешь стандартный игнайт, то для меня реально большая загадка что значит "GetEntPropEnt(attacker, Prop_Send, "m_hOwnerEntity");". Ты сам овнера устанавливал? Что ты пытаешься вытянуть? Вернёт ведь -1.
Проблема не в китайской азбуке, или чем бы оно тебе не казалось. Проблема в том, что ты стараешься не думать то, что ты делаешь)))
 

iamdss

Участник
Сообщения
126
Реакции
12
Немного оффтопа:
Проблема в том, что ты стараешься не думать то, что ты делаешь)))

Трудно думать в отсутствие нормальной документации. Сурсмодовская вики комментирует функции крайне скудно (я как бы и так догадываюсь, что, например IgniteEntity - Ignites an entity on fire), нет кросслинков, нет примеров кода. Впрочем, и за это им спасибо. Я привык к нормальной документации, из которой можно почерпнуть всё, что нужно. Пример - msdn. К тому же, я не сишник, в противном случае, мне было бы удобнее собрать свой вариант сервера ДМ из исходников, которые открыты. Но SM имеет один плюс - переносимость. Хотя всё равно это костыли. Мышки плакали, кололись, но продолжали жрать кактус ©


Если ты используешь стандартный игнайт, то для меня реально большая загадка что значит "GetEntPropEnt(attacker, Prop_Send, "m_hOwnerEntity");"

Действительно. Только сейчас я это понял. Владельца-то нет. Вот тут, кстати, ещё один вопрос. Как установить ему владельца? И возможно ли? Догадываюсь, что невозможно. В принципе, из кусков кода с форума я собрал поджигание и буду тестировать вечером, наверное, это было бы будет даже лучше.

И ещё вопрос. Могу ли я присваивать сущностям произвольные поля? Это очень полезно, если надо прицепить к сущности какую-то дополнительную информацию, чтобы не хранить её в переменных сурсмода и не заботиться о памяти.

Вопросы ещё будут, заглядывайте иногда =) Спасибо за помощь.
 

gibs

Фитиль народного волненья
Сообщения
722
Реакции
407
Мошенник
Немного оффтопа:
Трудно думать в отсутствие нормальной документации. Сурсмодовская вики комментирует функции крайне скудно (я как бы и так догадываюсь, что, например IgniteEntity - Ignites an entity on fire), нет кросслинков, нет примеров кода. Впрочем, и за это им спасибо. Я привык к нормальной документации, из которой можно почерпнуть всё, что нужно. Пример - msdn. К тому же, я не сишник, в противном случае, мне было бы удобнее собрать свой вариант сервера ДМ из исходников, которые открыты. Но SM имеет один плюс - переносимость. Хотя всё равно это костыли. Мышки плакали, кололись, но продолжали жрать кактус ©




Действительно. Только сейчас я это понял. Владельца-то нет. Вот тут, кстати, ещё один вопрос. Как установить ему владельца? И возможно ли? Догадываюсь, что невозможно. В принципе, из кусков кода с форума я собрал поджигание и буду тестировать вечером, наверное, это было бы будет даже лучше.

И ещё вопрос. Могу ли я присваивать сущностям произвольные поля? Это очень полезно, если надо прицепить к сущности какую-то дополнительную информацию, чтобы не хранить её в переменных сурсмода и не заботиться о памяти.

Вопросы ещё будут, заглядывайте иногда =) Спасибо за помощь.

Ну есть сдк, и вики валвовская. Всё довольно понятно даже на интуитивном уровне. Все коллбеки всегда имеются в .inc файле, их никто просто так с потолка не берёт.
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #11
Как установить ему владельца? И возможно ли?
PHP:
SetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity", client);

Могу ли я присваивать сущностям произвольные поля?
Вроде как нет.
Но если это что-то простое, типа индекса то можно запилит в тагрейт нейм
 

Reiko1231

AlexTheRegent
Сообщения
508
Реакции
1,336
Не гарантирую работу в HL2DM, но в CSS вроде как работает:
C-подобный:
// в игрока попали с нужного нам оружия
	...
	// поджигаем клиента
	IgniteEntity(iClient, 2.0);
	// после этого к игроку добавляется эффект огня, который мы получаем
	new iFireEntity = GetEntPropEnt(iClient, Prop_Data, "m_hEffectEntity");
	// устанавливаем ему овнера, кто его поджег
	SetEntPropEnt(iFireEntity, Prop_Data, "m_hOwnerEntity", iAttacker);
	...

// перед событием "игрок умер" (player_death, EventHookMode_Pre)
public Action:Ev_PlayerDeath(Handle:hEvent, const String:sEvName[], bool:bDontBroadcast)
{
	// получаем оружие, которым его убили
	decl String:sWeapon[64]; GetEventString(hEvent, "weapon", sWeapon, sizeof(sWeapon));
	// если это entityflame
	if ( strcmp(sWeapon, "entityflame") == 0 ) {
		// получаем самого игрока, получаем эффект на нем (огонь), и владельца этого эффекта
		new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid")),
			iFireEntity = GetEntPropEnt(iClient, Prop_Data, "m_hEffectEntity"),
			iFireOwner = GetEntPropEnt(iFireEntity, Prop_Data, "m_hOwnerEntity");
		
		// если владелец эффекта игрок и он на сервере
		if ( iFireOwner > 0 && iFireOwner <= MaxClients && IsClientInGame(iFireOwner) ) {
			// устанавливаем убийцу вручную
			SetEventInt(hEvent, "attacker", GetClientUserId(iFireOwner));
			// меняем оружие убийства, если это необходимо, для отображения в правом верхнем углу
			SetEventString(hEvent, "weapon", "awp");
		}
	}
	return Plugin_Continue;
}

Могу ли я присваивать сущностям произвольные поля?
Вроде как нет. Будет ошибка, что такое поле не найдено. Но у некоторых сущностей есть поля, которые наверное не используются, и в них можно что-нибудь хранить. Находятся методом тыка, например, prop_dynamic имеет такое поле "m_PredictableID" в ксс, но если в ксго это поле изменить, то слетают некоторые настройки объекта, и в целом этим лучше не пользоваться.
 

AlmazON

Не путать с самим yand3xmail
Сообщения
5,099
Реакции
2,755
прицепить к сущности какую-то дополнительную информацию
Строковые поля (из smlib):
PHP:
stock Entity_SetParentName(entity, const String:name[], any:...)
{
	decl String:format[128];
	VFormat(format, sizeof(format), name, 3);
	DispatchKeyValue(entity, "parentname", format);
}
stock Entity_SetGlobalName(entity, const String:name[], any:...)
{
	decl String:format[128];
	VFormat(format, sizeof(format), name, 3);
	DispatchKeyValue(entity, "globalname", format);
}
stock Entity_SetTargetName(entity, const String:name[], any:...)
{
	decl String:format[128];
	VFormat(format, sizeof(format), name, 3);
	DispatchKeyValue(entity, "target", format);
}
stock Entity_SetName(entity, const String:name[], any:...)
{
	decl String:format[128];
	VFormat(format, sizeof(format), name, 3);
	DispatchKeyValue(entity, "targetname", format);
}
А return Plugin_Changed;? Всё-таки событие изменяем (внутри функции стоило дописать).
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #14
IgniteEntity(iClient, 2.0);
// после этого к игроку добавляется эффект огня, который мы получаем
new iFireEntity = GetEntPropEnt(iClient, Prop_Data, "m_hEffectEntity");
// устанавливаем ему овнера, кто его поджег
SetEntPropEnt(iFireEntity, Prop_Data, "m_hOwnerEntity", iAttacker);
Не знал что при IgniteEntity ентити огня устанавливается клиенту в m_hEffectEntity.
Это пригодится.
 

iamdss

Участник
Сообщения
126
Реакции
12
Спасибо за ценную информацию, материала более чем достаточно. Отпишу по результатам.

Добавлено через 3 часа 56 минут
Проверил. Похоже, это:

// устанавливаем убийцу вручную
SetEventInt(hEvent, "attacker", GetClientUserId(iFireOwner));

или не так работает в ДМ, или в ДМ другой параметр ивента отвечает за килл. Игрок умирает, в HUD отображается верно, но килл не засчитывается. Сейчас попытаюсь найти что-то в документации.

А return Plugin_Changed;? Всё-таки событие изменяем (внутри функции стоило дописать).

Это верно, но не работает. Если возвращаем Plugin_Changed, то ни в HUD не отображается убийство, ни фраг не засчитывается. Как будто ничего не меняли. Я затрудняюсь сказать, почему так.

Добавлено через 5 часов 21 минуту
В принципе, с фрагами всё просто, выдаю вручную:

C-подобный:
val = GetClientFrags(attacker);
SetEntProp(attacker, Prop_Data, "m_iFrags", val + 1);

val = GetClientDeaths(client);
SetEntProp(client, Prop_Data, "m_iDeaths", val + 1);

Не знаю, насколько я угадал, но это работает.

На вопрос про Plugin_Changed ответа не нашёл. Без него всё работает правильно, как ни странно.

А можно ли управлять свойствами огня, созданного через IgniteEntity?
 
Последнее редактирование:
Сверху Снизу