Перейти к содержимому


Фотография

SDKHooks_TakeDamage и SDKHook_OnTakeDamage

Урон

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 7

#1 PawnLomaster

PawnLomaster

    Участник

  • Пользователь
  • PipPip
  • 116 сообщений

Отправлено 22 Июль 2021 - 6:33

Привет, форумчане!
Ситуация примерно такая: один плагин наносит урон игроку через SDKHooks_TakeDamage, а другой плагин фиксирует факт урона через hook SDKHooks_OnTakeDamage.
Разработчики SourceMod намеренно исключили возможность отслеживать урон от SDKHooks_TakeDamage через SDKHooks_OnTakeDamage, чтобы предотвратить зацикливание при нанесении урона в отслеживающем hook'е.
Вариант обхода через entity "point_hurt" не подходит, так как перезаписывается id атакующего на id этой entity. Плюс ко всему не учитывается оружие, с помощью которого был нанёс урон. Оборачивать в native и forward вообще грустно.
Может кто знает другие способы?


Сообщение отредактировал PawnLomaster: 22 Июль 2021 - 6:37


#2 history_maker

history_maker

    Пользователь

  • Пользователь
  • PipPipPip
  • 327 сообщений

Отправлено 22 Июль 2021 - 14:51

В самой игре есть ивент player_hurt, через него пробовали отследить входящий урон?

#3 PawnLomaster

PawnLomaster

    Участник

  • Пользователь
  • PipPip
  • 116 сообщений

Отправлено 23 Июль 2021 - 0:00

В самой игре есть ивент player_hurt, через него пробовали отследить входящий урон?

Первым делом, но там есть ряд проблем.
1) Оружие - это строка. Мне нужен id entity для разного рода манипуляций. Так то в теории можно набросать функцию, которая будет сопоставлять строку из эвента с оружием атакующего, но это не всегда возможно.
2) Дублирование. Событие урона будет обрабатываться дважды. Сначала в hook'е, потом в event'е (имеется в виду естественный урон. Не через native)
3) Невозможность манипулировать уроном. Например увеличить или уменьшить урон.


Сообщение отредактировал PawnLomaster: 23 Июль 2021 - 0:10


#4 PawnLomaster

PawnLomaster

    Участник

  • Пользователь
  • PipPip
  • 116 сообщений

Отправлено 05 Август 2021 - 21:17

Кажись я нашёл один способ, но это немного запарно. Недавние обновления L4D2 принесли VScript функции TakeDamage и TakeDamageEx (https://developer.va...tions#CEntities). Если обернуть эти функции в SourceMod, то откроется дополнительная возможность наносить урон.
Одна проблема. VScripts используют указатели,а не индексы, как в SourceMod. Встроенной функции для получения указателя по индексу энтити нет.  Тем не менее её можно написать самостоятельно. Выглядит это примерно так

::FindEntityByID <- function(id)
{
 local ent = CEntities.First();
 do
 {
  if(ent.IsValid() && ent.GetEntityIndex() == id)
   return ent;
 }
 while((ent=CEntities.Next(ent))!=null);
 return null;
}

Но как итог постоянно получаю местный аналог NullReferenseExeption. Что, где, кого не пишет. Даже позицию ошибки. Только ошибку AN ERROR HAS OCCURED [Accessed null instance]

Это первое.
Второе - это обернуть функции нанесения урона. Это есть

Скрытый текст


Может кто помочь провернуть это дельце со squirrel?


Сообщение отредактировал PawnLomaster: 05 Август 2021 - 21:28


#5 PawnLomaster

PawnLomaster

    Участник

  • Пользователь
  • PipPip
  • 116 сообщений

Отправлено 25 Сентябрь 2021 - 2:20

В общем и целом всё, что я пытался крутить со скриптами, оказалось полной ерундой. Решается проблема буквально в одну строчку скрипта (Потому что в VScripts есть функция преобразования индекса в скриптовый указатель).
 

void TakeDamage2(int iVictim, int iAttacker, float flDamage, int iDmgType)
{
	RunScript("Ent(%d).TakeDamage(%.1f, %d, Ent(%d));", iVictim, flDamage, iDmgType, iAttacker);
}

//Каюсь, эта функция не моя. Но у кого позаимствовал, уже не помню :P
void RunScript(const char[] arguments, any ...)
{
	char vscript[PLATFORM_MAX_PATH];
	VFormat(vscript, sizeof(vscript), arguments, 2);
	
	static int iScriptLogic = INVALID_ENT_REFERENCE;
	if(iScriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(iScriptLogic))
	{
		iScriptLogic = EntIndexToEntRef(CreateEntityByName("logic_script"));
		if(iScriptLogic == INVALID_ENT_REFERENCE || !IsValidEntity(iScriptLogic))
                {
		     LogError("Could not create 'logic_script");
                     return;
                }

		DispatchSpawn(iScriptLogic);
	}
	
	SetVariantString(vscript);
	AcceptEntityInput(iScriptLogic, "RunScriptCode");
	AcceptEntityInput(iScriptLogic, "Kill");	
}

Вызов TakeDamage2 вызовет все хуки и нанесёт урон с сохранением индекса атакующего. Profit.


Сообщение отредактировал PawnLomaster: 25 Сентябрь 2021 - 3:09

  • 8rutu5 это нравится

#6 dragokas

dragokas

    Постоянный пользователь

  • Пользователь
  • PipPipPipPipPip
  • 792 сообщений

Отправлено 11 Октябрь 2021 - 10:56

Делай урон энтитей point_hurt

void HurtEntity(int target, int attacker, int damage = 1, int damagetype = 8) // thanks to SilverShot
{
	char sTemp[16];
	int entity = CreateEntityByName("point_hurt");
	Format(sTemp, sizeof(sTemp), "ext%d%d", EntIndexToEntRef(entity), attacker);
	DispatchKeyValue(target, "targetname", sTemp);
	DispatchKeyValue(entity, "DamageTarget", sTemp);
	IntToString(damage, sTemp, sizeof(sTemp));
	DispatchKeyValue(entity, "Damage", sTemp);
	IntToString(damagetype, sTemp, sizeof(sTemp));
	DispatchKeyValue(entity, "DamageType", sTemp);
	DispatchSpawn(entity);
	AcceptEntityInput(entity, "Hurt", attacker > 0 ? attacker : -1);
	RemoveEdict(entity);
}

или еще проще, одной строкой стоком 

SlapPlayer(client, 5, false);


#7 dragokas

dragokas

    Постоянный пользователь

  • Пользователь
  • PipPipPipPipPip
  • 792 сообщений

Отправлено 21 Октябрь 2021 - 18:26

В последнем билде sm 1.11.6775 добавили возможность снятия блокировки хука урона от натива SDKHooks_TakeDamage.

/**
 * Applies damage to an entity
 *
 * @note Force application is dependent on game and damage type(s)
 *
 * @param entity         Entity index taking damage
 * @param inflictor      Inflictor entity index
 * @param attacker       Attacker entity index
 * @param damage         Amount of damage
 * @param damageType     Bitfield of damage types
 * @param weapon         Weapon index (orangebox and later) or -1 for unspecified
 * @param damageForce    Velocity of damage force
 * @param damagePosition Origin of damage
 * @param bypassHooks    If true, bypass SDK hooks on OnTakeDamage
 * @error                Invalid entity, attacker, inflictor, or weapon entity.
 */
native void SDKHooks_TakeDamage(int entity, int inflictor, int attacker,
		float damage, int damageType=DMG_GENERIC, int weapon=-1,
		const float damageForce[3]=NULL_VECTOR, const float damagePosition[3]=NULL_VECTOR,
		bool bypassHooks = true);

Последний параметр установите false.



#8 PawnLomaster

PawnLomaster

    Участник

  • Пользователь
  • PipPip
  • 116 сообщений

Отправлено 25 Октябрь 2021 - 13:00

SlapPlayer(client, 5, false);

Так теряется атакующий

 

 

Делай урон энтитей point_hurt

А вот это уже интереснее. Не знал, что point_hurt может брать активатора за атакующего. Надо было лучше читать пометки в вики https://developer.va...wiki/Point_hurt
Думаю, что это эффективнее, чем дополнительно подтягивать VScripts.
Хотя, если нужно указывать определённого "причинителя" и определённое оружие, то TakeDamageEx в VScripts выигрывает.

 

В последнем билде sm 1.11.6775 добавили возможность снятия блокировки хука урона от натива SDKHooks_TakeDamage.

Круто! Но лучше пусть 1.11 перейдёт сначала из dev в stable. А потом можно использовать. Так даже эффективнее всего будет.





Темы с аналогичным тегами Урон

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных