21/01/2015, 05:29 PM
(Última modificación: 15/05/2015, 09:00 PM por meTaLiCroSS.)
Me nació querer publicar esto ya que, a diferencia del resto, se ve poco y para muchos debe ser interesante
Si bien saben, el cuchillo tiene 2 ataques, el Primario, y Segundario.
► El Primario se divide en 2:
Es por eso que al estar pegando con Primario, el primero siempre quita más y el resto 15.
► El Segundario se divide en 2:
El CS calcula la "espada" del jugador con respecto a sus angulos de vision. No es especificamente la espalda, puesto que es solo la parte trasera de su vision -> infiero que si le das en los pies también habrá multiplo por 3.
Todos los daños realizados con el cuchillo pasan por la multiplicación de daño según el hitbox del jugador (si es a una entidad, pasa directo), puesto que si quieres detectar ataque de un Knife con respecto a su daño, será falso positivo en más del 50% de los casos.
Es por eso que aquí les dejo métodos hábiles y decentes para detectar el ataque de un Knife.
Partamos por lo más sencillo. Estos metodos son validos para TakeDamage y TraceAttack, debido que uno llama al otro. Lo que si:
TakeDamage pasa el daño ya multiplicado por la diferencia de los hitboxes
TraceAttack pasa el daño entero, dentro de esta misma funcion llama a TakeDamage con el daño multiplicado.
Todo depende de lo que quieran hacer.
1) Los Damage Bits del daño siempre serán DMG_BULLET | DMG_NEVERGIB, es primordial su chequeo y no es costoso de rendimiento debido que el parametro DamageBits es una variable ya.
2) El Atacante será siempre igual a quien Infringe el Damage. (attacker == inflictor)
3) Antes de efectuar el Daño, se llama SendWeaponAnim actualizando el valor de pev->weaponanim, el que podemos utilizar para chequear.
*** No incluyo el metodo de chequeo con los botones debido que un usuario puede estar presionando los 2 al mismo tiempo y causar falsos positivos. Hay un metodo de arreglarlo pero no vale la pena con lo escrito arriba. ***
Se vería algo así:
Para poder detectar si fue por la espalda, podemos transformar el codigo del mismo SDK. Me quedó algo así, sean libres de utilizarlo
Y en conjunto con el plugin, sería:
EXISTE OTRO METODO, no llama al módulo, pero si genera muchas llamadas. Es útil y pueden utilizarlo tal cual como el code de arriba. Solo que aquí utilizamos variables.
Dentro de PrimaryAttack y SecondaryAttack no hay restricciones de por medio en las que no exista un ataque de cuchillo. (A excepcion de SecondaryAttack cuando se tiene Escudo, por que no hay daño)
Es por eso que la asignacion en las variables es inmediata, no hay mayor enrredo ahí.
Cualquier duda pueden avisar, es un area algo rebuscada y me animé en aclarar algunas cosas con esta guia. espero la reputacion gordos de $%#&@
Referencias: https://github.com/Arkshine/CSSDK/blob/m..._knife.cpp
Si bien saben, el cuchillo tiene 2 ataques, el Primario, y Segundario.
► El Primario se divide en 2:
- Primer Ataque: Si han pasado más de 0.4 segundos desde el Primer Ataque, este dará 20 de Damage.
- Ataque Constante: Condición contraria a la anterior, este dará 15 de Damage.
Es por eso que al estar pegando con Primario, el primero siempre quita más y el resto 15.
► El Segundario se divide en 2:
- Espalda: Si se le llega a dar un Stab en la Espalda del Jugador, este dará 195 (65 * 3) de Damage.
- Cuerpo: En cualquier parte del cuerpo excluyendo la espalda, este dará 65 de Damage.[/b].
El CS calcula la "espada" del jugador con respecto a sus angulos de vision. No es especificamente la espalda, puesto que es solo la parte trasera de su vision -> infiero que si le das en los pies también habrá multiplo por 3.
Todos los daños realizados con el cuchillo pasan por la multiplicación de daño según el hitbox del jugador (si es a una entidad, pasa directo), puesto que si quieres detectar ataque de un Knife con respecto a su daño, será falso positivo en más del 50% de los casos.
Es por eso que aquí les dejo métodos hábiles y decentes para detectar el ataque de un Knife.
Partamos por lo más sencillo. Estos metodos son validos para TakeDamage y TraceAttack, debido que uno llama al otro. Lo que si:
TakeDamage pasa el daño ya multiplicado por la diferencia de los hitboxes
TraceAttack pasa el daño entero, dentro de esta misma funcion llama a TakeDamage con el daño multiplicado.
Todo depende de lo que quieran hacer.
1) Los Damage Bits del daño siempre serán DMG_BULLET | DMG_NEVERGIB, es primordial su chequeo y no es costoso de rendimiento debido que el parametro DamageBits es una variable ya.
2) El Atacante será siempre igual a quien Infringe el Damage. (attacker == inflictor)
3) Antes de efectuar el Daño, se llama SendWeaponAnim actualizando el valor de pev->weaponanim, el que podemos utilizar para chequear.
*** No incluyo el metodo de chequeo con los botones debido que un usuario puede estar presionando los 2 al mismo tiempo y causar falsos positivos. Hay un metodo de arreglarlo pero no vale la pena con lo escrito arriba. ***
Se vería algo así:
Código PHP:
#include <amxmodx>
#include <hamsandwich>
#include <engine>
enum
{
KNIFE_IDLE1 = 0,
KNIFE_SLASH1,
KNIFE_SLASH2,
KNIFE_DRAW,
KNIFE_STAB,
KNIFE_STAB_MISS,
KNIFE_MIDSLASH1,
KNIFE_MIDSLASH2
};
public plugin_init()
{
register_plugin("Deteccion de Ataques de Cuchillo", "0.1", "PM");
RegisterHam(Ham_TakeDamage, "player", "OnPlayer_TakeDamage");
}
public OnPlayer_TakeDamage(iVictim, iInflictor, iAttacker, Float:flDamage, bitsDamageType)
{
if(iAttacker == iInflictor && bitsDamageType == (DMG_BULLET|DMG_NEVERGIB) && is_user_alive(iAttacker) && get_user_weapon(iAttacker) == CSW_KNIFE)
// is_user_alive lo dejo al final, asi no hago que llame siempre a la native vez que se llame TakeDamage
// dejando primero los chequeos de parametros que no hacen nada en comparacion a una native.
{
new iAnim = entity_get_int(iAttacker, EV_INT_weaponanim);
// no le doy static debido a que TakeDamage, puede ser brutalmente llamado en hordas de ataques, pero no es el caso de un Knife
if(KNIFE_STAB <= iAnim <= KNIFE_STAB_MISS)
client_print(iVictim, print_center, "Te han atacado con un Golpe Segundario de Cuchillo");
else if(KNIFE_MIDSLASH1 <= iAnim <= KNIFE_MIDSLASH2) // es necesario aun asi, hay que ponerse en cualquier caso...
client_print(iVictim, print_center, "Te han atacado con un Golpe Primario de Cuchillo");
}
}
Para poder detectar si fue por la espalda, podemos transformar el codigo del mismo SDK. Me quedó algo así, sean libres de utilizarlo
Código PHP:
stock IsBackStab(iVictim, iAttacker)
{
// Angulos del Atacante
new Float:vecFwd[3];
entity_get_vector(iAttacker, EV_VEC_v_angle, vecFwd);
angle_vector(vecFwd, ANGLEVECTOR_FORWARD, vecFwd);
vecFwd[2] = 0.0 // 3D a 2D
xs_vec_normalize(vecFwd, vecFwd);
// Angulos de Cuerpo de la Victima
new Float:vecVictimFwd[3]
entity_get_vector(iVictim, EV_VEC_angles, vecVictimFwd);
angle_vector(vecVictimFwd, ANGLEVECTOR_FORWARD, vecVictimFwd);
vecVictimFwd[2] = 0.0 // 3D a 2D
return xs_vec_dot(vecFwd, vecVictimFwd) > 0.8;
}
Y en conjunto con el plugin, sería:
Código PHP:
#include <amxmodx>
#include <hamsandwich>
#include <engine>
#include <xs>
enum
{
KNIFE_IDLE1 = 0,
KNIFE_SLASH1,
KNIFE_SLASH2,
KNIFE_DRAW,
KNIFE_STAB,
KNIFE_STAB_MISS,
KNIFE_MIDSLASH1,
KNIFE_MIDSLASH2
};
public plugin_init()
{
register_plugin("Deteccion de Ataques de Cuchillo", "0.1", "PM");
RegisterHam(Ham_TakeDamage, "player", "OnPlayer_TakeDamage");
}
public OnPlayer_TakeDamage(iVictim, iInflictor, iAttacker, Float:flDamage, bitsDamageType)
{
if(iAttacker == iInflictor && bitsDamageType == (DMG_BULLET|DMG_NEVERGIB) && is_user_alive(iAttacker) && get_user_weapon(iAttacker) == CSW_KNIFE)
// is_user_alive lo dejo al final, asi no hago que llame siempre a la native vez que se llame TakeDamage
// dejando primero los chequeos de parametros que no hacen nada en comparacion a una native.
{
if( (KNIFE_STAB <= entity_get_int(iAttacker, EV_INT_weaponanim) <= KNIFE_STAB_MISS) && IsBackStab(iVictim, iAttacker) )
client_print(iVictim, print_center, "Te han atacado con un Golpe Segundario de Cuchillo, y por la espalda, uugh");
}
}
stock IsBackStab(iVictim, iAttacker)
{
// Angulos del Atacante
new Float:vecFwd[3];
entity_get_vector(iAttacker, EV_VEC_v_angle, vecFwd);
angle_vector(vecFwd, ANGLEVECTOR_FORWARD, vecFwd);
vecFwd[2] = 0.0 // 3D a 2D
xs_vec_normalize(vecFwd, vecFwd);
// Angulos de Cuerpo de la Victima
new Float:vecVictimFwd[3]
entity_get_vector(iVictim, EV_VEC_angles, vecVictimFwd);
angle_vector(vecVictimFwd, ANGLEVECTOR_FORWARD, vecVictimFwd);
vecVictimFwd[2] = 0.0 // 3D a 2D
return xs_vec_dot(vecFwd, vecVictimFwd) > 0.8;
}
EXISTE OTRO METODO, no llama al módulo, pero si genera muchas llamadas. Es útil y pueden utilizarlo tal cual como el code de arriba. Solo que aquí utilizamos variables.
Código PHP:
#include <amxmodx>
#include <hamsandwich>
#include <engine>
#include <xs>
enum KnifeAttack
{
KA_NONE = 0,
KA_SLASH,
KA_STAB
}
new KnifeAttack:g_iKnifeAttack
public plugin_init()
{
register_plugin("Deteccion de Ataques de Cuchillo", "0.1", "PM");
RegisterHam(Ham_TakeDamage, "player", "OnPlayer_TakeDamage");
RegisterHam(Ham_Weapon_PrimaryAttack, "weapon_knife", "OnKnife_PrimaryAttack")
RegisterHam(Ham_Weapon_SecondaryAttack, "weapon_knife", "OnKnife_SecondaryAttack")
RegisterHam(Ham_Weapon_PrimaryAttack, "weapon_knife", "OnKnife_Attack_Post", true)
RegisterHam(Ham_Weapon_SecondaryAttack, "weapon_knife", "OnKnife_Attack_Post", true)
}
public OnPlayer_TakeDamage(iVictim, iInflictor, iAttacker, Float:flDamage, bitsDamageType)
{
if(iAttacker == iInflictor && bitsDamageType == (DMG_BULLET|DMG_NEVERGIB) && is_user_alive(iAttacker))
// is_user_alive lo dejo al final, asi no hago que llame siempre a la native vez que se llame TakeDamage
// dejando primero los chequeos de parametros que no hacen nada en comparacion a una native.
{
if( g_iKnifeAttack == KA_STAB && IsBackStab(iVictim, iAttacker) )
client_print(iVictim, print_center, "Te han atacado con un Golpe Segundario de Cuchillo, y por la espalda, uugh");
}
}
public OnKnife_PrimaryAttack() g_iKnifeAttack = KA_SLASH;
public OnKnife_SecondaryAttack() g_iKnifeAttack = KA_STAB;
public OnKnife_Attack_Post() g_iKnifeAttack = KA_NONE;
stock IsBackStab(iVictim, iAttacker)
{
// Angulos del Atacante
new Float:vecFwd[3];
entity_get_vector(iAttacker, EV_VEC_v_angle, vecFwd);
angle_vector(vecFwd, ANGLEVECTOR_FORWARD, vecFwd);
vecFwd[2] = 0.0 // 3D a 2D
xs_vec_normalize(vecFwd, vecFwd);
// Angulos de Cuerpo de la Victima
new Float:vecVictimFwd[3]
entity_get_vector(iVictim, EV_VEC_angles, vecVictimFwd);
angle_vector(vecVictimFwd, ANGLEVECTOR_FORWARD, vecVictimFwd);
vecVictimFwd[2] = 0.0 // 3D a 2D
return xs_vec_dot(vecFwd, vecVictimFwd) > 0.8;
}
Dentro de PrimaryAttack y SecondaryAttack no hay restricciones de por medio en las que no exista un ataque de cuchillo. (A excepcion de SecondaryAttack cuando se tiene Escudo, por que no hay daño)
Es por eso que la asignacion en las variables es inmediata, no hay mayor enrredo ahí.
Cualquier duda pueden avisar, es un area algo rebuscada y me animé en aclarar algunas cosas con esta guia. espero la reputacion gordos de $%#&@
Referencias: https://github.com/Arkshine/CSSDK/blob/m..._knife.cpp
Strings en goldsrc (STRING, ALLOC_STRING, MAKE_STRING) - GoldSrc: gamedll, hlsdk, etc - Obteniendo nombres de texturas de mapas - FindEntityByString y derivados - Detectar Ataques de Knife - El Parametro fNoMonsters de los Traces - Funcion: AddToFullPack - Compresión de digitos - Native: register_event
► Si vas a pedirme ayuda con code vía Mensaje Privado, anda pensando primero como me vas a cargar la PayPal... ◄
► Si vas a pedirme ayuda con code vía Mensaje Privado, anda pensando primero como me vas a cargar la PayPal... ◄