Raised This Month: $51 Target: $400
 12% 

Tutorial de Traceline (Fakemeta)


  
 
 
Thread Tools Display Modes
Author Message
Rama-PH
Member
Join Date: Feb 2009
Location: Colegiales, Argentina
Old 11-17-2012 , 22:21   Tutorial de Traceline (Fakemeta)
#1

Este tema posee contenido traducido por Rama-PH de:
http://forums.alliedmods.net/showthread.php?t=66076

Autor:Nomexous
Traductor: Rama-PH


Teoría

¿Qué es "Traceline" realmente? Traceline es una función en el engine de Half-Life que es usada para dibujar líneas de un punto a otro en un espacio 3D. Puede devolver información, como quien o que fue golpeado o atravezado, y muchas otras variantes útiles.

El Traceline se utiliza en todos los modos con el objetivo de determinar donde un jugador está mirando y disparando.
Es por ello que resulta muy útil aprender como manipular el Traceline como uno lo desee.


El modo en el que se programa (en este caso va a ser el CS) se encuentra separado del engine del HL (Half-Life). El Metamod (y por lo tanto su extención, AMX Mod X), se encuentra entre el modo DLL y el engine del HL. Esto nos da la habilidad de interceptar cualquier cosa que el modo DLL le envía al engine y vice versa. Entonces, cuando el CS le pide al engine del HL que calcule un Traceline, podemos cambiar completamente el resultado de este.


El Código

Vamos a usar forwards en Fakemeta para capturar la comunicación entre el CS y el engine del HL. Esto significa que que vamos a ver la información que el CS le iba a pasar al engine para poder calcular el Traceline.

PHP Code:
#include <amxmodx>
#include <fakemeta>

public plugin_init()
{
    
register_plugin("Tutorial de Traceline""1.0""Nomexous (Autor original)")
    
    
register_forward(FM_TraceLine"traceline_forward")
}

public 
traceline_forward(Float:start[3], Float:end[3], conditionsidtrace)
{
    
// Nuestra Traceline forward.

El significado de los argumentos pasados a nuestra función pueden no estar muy claros, por ello paso a explicarlos:

Float:start[3] El origen del lugar donde la Traceline es creada.

Float:end[3] El origen del lugar donde la Traceline termina.

conditions Especifica si ignorar o no ciertas entidades cuando se dibuja el Traceline. Los valores pueden ser:
DONT_IGNORE_MONSTERS, IGNORE_GLASS, IGNORE_MISSLE, and IGNORE_MONSTERS.

id Esta es la entidad a ignorar cuando se dibuja el Traceline. Se supone que la Traceline se dibuja desde el origen de una entidad (el origen está dentro de la entidad) hasta otro punto. Con Tracelines dibujados desde un jugador, id es el index del jugador que está disparando el Traceline.

trace El resultado del trazo. Esta es la parte más importante. Contiene la información sobre que fue golpeado por el Traceline, entre otras cosas. Hay que usar get_tr2 y set_tr2 con esto.

El Resultado del Trace

Esta es la parte más excitante. La variable
trace retiene información detallada, que puede ser recibida así:

PHP Code:

public traceline_forward(Float:start[3], Float:end[3], conditionsidtrace)
{

    
// Hay más constantes TR_* que las que están acá; pero estas son las que
    // más uso.

    
    
new hit get_tr2(traceTR_pHit)
    
// Lo que fue golpeado por el Traceline. Puede ser el index de un jugador,
    // el index de una entidad, 0 (parte del mapa), o -1 (no golpeó nada;
    // no pasa con Tracelines de jugadores).
    
    
new hitgroup get_tr2(traceTR_iHitgroup)
    
// Si el Traceline golpea a otro jugador, lo que devuelva va a ser HIT_HEAD,
    // HIT_CHEST, HIT_LEFTLEG... etc. Si el Traceline golpea parte del mapa, 
    // esto devuelve HIT_GENERIC.
    
    
new Float:fraction
    get_tr2
(traceTR_flFractionfraction)
    
// Devuelve un número entre 0.0 y 1.0, indicando cuan lejos el Traceline
    // viajo del principio a fin antes de golpear algo. Dependiendo
    // de que condiciones fueron pasadas a la función forward del Traceline 
    // puede ser una pared u otra entidad.
    
    
new Float:end_origin[3]
    
get_tr2(traceTR_vecEndPosend_origin)
    
// El final oficial del Traceline. No necesariamente lo mismo que el
    // segundo argumento pasado a la función forward de este Traceline. 
    
    
new Float:normal[3]
    
get_tr2(traceTR_vecPlaneNormalnormal)
    
// Devuelve un vector de 1 unidad de largo normal al lugar donde golpeo 
    // el Traceline.
    // Noten que "normal" tiene una connotación especial. No significa "regular". 
Vean esto si no saben lo que se refiere con el "normal" en este contexto.

Ahora, cambiar este valor es tan facil como usar la función set_tr2

Un plugin Potencialmente Malvado

Estoy seguro de que todos jugaron en un servidor que permitía headshots unicamente. Es una buena práctica, los disparos al cuerpo no causan daño, los headshots matan instantaneamente, blah blah. Pero, ¿qué pasaría si pudieramos redireccionar un disparo en cualquier parte del cuerpo a la cabeza? ¿Los disparos a los pies podrían ser headshots? Sería buenisimo!

PHP Code:
public traceline_forward(Float:start[3], Float:end[3], conditionsidtrace)
{
    
set_tr2(traceTR_iHitgroupHIT_HEAD)
    return 
FMRES_IGNORED

Es bastante sorprendente, realmente. Pruebenlo. Si están acostumbrados a ver mucha sangre a causa de un headshot, van a estar asombrados al ver esa cantidad de sangre salir de un "footshoot". Las Shoutgund son extremadamente mortales, ya que todos los perdigones (balas) son redireccionados a la cabeza al mismo tiempo. Hacé un if (is_user_admin(id)) y vas a tener un plugin malvado muajaj.

Pero, resulta medio difícil tratar de esconder el hecho de que la sangre de un headshot salió del pie o del estómago, o cualquier parte del cuerpo donde se dispare. Lo que se quiere es que la sangre también se redireccione a la cabeza. Como esto depende del Traceline, tenemos todo el control del asunto:

PHP Code:

public traceline_forward(Float:start[3], Float:end[3], conditionsidtrace)
{
    
set_tr2(traceTR_iHitgroupHIT_HEAD// Redirecciona el disparo a la cabeza
    
    // Las variables de angulo no tienen uso aca.
    
static hitFloat:head_origin[3], Float:angles[3]
    
    
hit get_tr2(traceTR_pHit// El que recibe el disparo
    
engfunc(EngFunc_GetBonePositionhit8head_originangles// Busca el origen del hueso de la cabeza (8)
    
    
set_tr2(traceTR_vecEndPoshead_origin// La sangre sale de la cabeza!
    
    
return FMRES_IGNORED

Esto es aún más malvado. Ahora podemos ir por nuestro servidor, haciendo headshots sin sangre inexplicable. Aunque ahora tendrías que explicar porque no podés hacer nada más que headshots jaja.

Podés claramente cambiar el jugador al cual le disparás. Considerando este anti-team attack plugin para cs:

PHP Code:

#include <amxmodx>
#include <fakemeta>
#include <cstrike>

public plugin_init()
{
    
register_plugin("No team Attack""1.0""Nomexous (Autor del tema original)")
    
    
register_forward(FM_TraceLine"traceline_forward")
}

public 
traceline_forward(Float:start[3], Float:end[3], conditionsidtrace)
{
    static 
hit
    
    hit 
get_tr2(traceTR_pHit)
    
    
// El "id" es el index del que dispara.
    
if (cs_get_user_team(id) == cs_get_user_team(hit))
    {
        
// Se redirecciona a si mismo!
        
set_tr2(traceTR_pHitid)
    }
    
    return 
FMRES_IGNORED

La sangre va a seguir saliendo de la persona que está siendo disparada, pero el daño lo va a recibir el que dispara.
Las personas van a dejar de querer disparar a los de su team!

Subí un plugin (Shot Administration) que demuestra la malvada capacidad de manipular el Traceline. Miren; tracehull también es hookeado (para el daño del cuchillo)

Otros Usos Menos Malvados Del TraceLine

Ahora vamos a usar Tracelines para hacer cosas fuera del contexto de un jugador apuntando. Usando
engfunc() podemos dibujar nuestros propios Tracelines para ver lo que golpeamos. Claramente no estamos disparando y provocando un daño, pero con la información que el resultado del trazo nos da, puede ser igual de útil.

Veamos si dos orígenes (comienzo y fin) están a la vista:

PHP Code:
stock bool:is_in_line_of_sight(Float:origin1[3], Float:origin[2], bool:ignore_players true)
{
    new 
trace 0
    engfunc
(EngFunc_TraceLineorigin1origin2, (ignore_players IGNORE_MONSTERS DONT_IGNORE_MONSTERS), 0trace)
    
    new 
Float:fraction
    get_tr2
(traceTR_flFractionfraction)
    
    return (
fraction == 1.0) ? true false



Este stock ve cuan lejos fue el Traceline antes de golpear con algo. Si TR_flFraction es 1.0 significa que fue 100% del trayecto sin golpear ningún obstáculo. Entonces, los dos orígenes están a la vista.
Otra alternativa es ver lo que TR_pHit devuelve. Si devuelve -1 no golpeaste nada (entonces los dos orígenes están a la vista). Si devuelve 0 significa que golpeaste una parte del mapa (se asume que es una pared), y todo lo demás es el index de una entidad que se cruzó.
Tené cuidado; puede que no sea un jugador. Puede ser una puerta o un func_wall.

Ahora, hagamos uso de la parte
TR_vecPlaneNormal del resultado del trazo. Hay múltiples cosas para las que puede ser útil esto. Acá mostraré como dibujar un laser normal a una superficie.

Cuando el trazo golpea algo,
TR_vecPlaneNormal va a tener un vector de unidad (1 unidad en largo) almacenada en ella, mirando perpendicularmente afuera de la superficie en el lugar donde golpeó. Para obtener el punto final del laser, tenemos que extender el largo del vector normal y agregarlo al origen de donde queremos que el laser empieze. Acá hay un ejemplo:

PHP Code:

#include <amxmodx>
#include <fakemeta>

#define PLUGIN "Dibujar un laser normal"
#define VERSION "1.0"
#define AUTHOR "Nomexous (Autor original del tema)"

new beampoint

public plugin_precache()
{
    
// Necesario para mostrar el laser.
    
beampoint precache_model("sprites/laserbeam.spr")
}

public 
plugin_init()
{
    
register_plugin(PLUGINVERSIONAUTHOR)
    
    
// Incluí el plugin entero porque para poder dibujar el laser, necesitas precachear un sprite.
    // Incorporá estos elementos en tu propio plugin.
    // El shoot_laser() va a (si la entidad está en el piso) disparar un laser desde la entidad, normal a la superficie en la que está .


}

public 
shoot_laser(ent)
{
    
// Conseguimos el origen de la entidad
    
new Float:origin[3]
    
pev(entpev_originorigin)
    
    
// Queremos trazar hasta elk piso, si está allí.
    
new Float:traceto[3]
    
traceto[0] = origin[0]
    
traceto[1] = origin[1]
    
traceto[2] = origin[2] - 10.0
    
    
new trace 0
    
// Dibujamos el Traceline. Estamos asumiendoel que el objteto está en el piso.
    
engfunc(EngFunc_TraceLineorigintracetoIGNORE_MONSTERSenttrace)
    
    new 
Float:fraction
    get_tr2
(traceTR_flFractionfraction)
    
// Si no golpeamos nada, entonces no obtendremos un TR_vecPlaneNormal válido.
    
if (fraction == 1.0) return
    
    new 
Float:normal[3]
    
get_tr2(traceTR_vecPlaneNormalnormal)
    
// Vamos a multiplicar el vector normal por un escalar para hacerlo más largo.
    
normal[0] *= 400.0 // Matematicamente, multiplicamos el largo del vector por 400*(3)^(1/2),
    
normal[1] *= 400.0 // o, en palabras, cuatrocientas veces por tres four.
    
    // Para conseguir el punto final, agregamos el vector normal y el origen.
    
new Float:endpoint[3]
    
endpoint[0] = origin[0] + normal[0]
    
endpoint[1] = origin[1] + normal[1]
    
endpoint[2] = origin[2] + normal[2]
    
    
// Finalmente, dibujamos desde el laser!
    
draw_laser(originendpoint100// Lo dejamos estar por 10 segundos. El tiempo que se mantiene está en 10ths de un segundo.
}

public 
draw_laser(Float:start[3], Float:end[3], staytime)
{                    
    
message_begin(MSG_ALLSVC_TEMPENTITY)
    
write_byte(TE_BEAMPOINTS)
    
engfunc(EngFunc_WriteCoordstart[0])
    
engfunc(EngFunc_WriteCoordstart[1])
    
engfunc(EngFunc_WriteCoordstart[2])
    
engfunc(EngFunc_WriteCoordend[0])
    
engfunc(EngFunc_WriteCoordend[1])
    
engfunc(EngFunc_WriteCoordend[2])
    
write_short(beampoint)
    
write_byte(0)
    
write_byte(0)
    
write_byte(staytime// En decimas de segundo.
    
write_byte(10)
    
write_byte(1)
    
write_byte(255// Rojo
    
write_byte(0// Verde
    
write_byte(0// Azul
    
write_byte(127)
    
write_byte(1)
    
message_end()


Bueno, eso es todo por ahora. Con suerte pudieron aprender más acerca del Traceline y pueden tomar ventaja de ello!

Espero que mi traducción les haya gustado, fue muy placentero traducirlo ya que adquerí el conocimiento mucho más facilmente.



Rama-PH is offline
BlackFur
BANNED
Join Date: Apr 2012
Location: RCL
Old 11-18-2012 , 00:08   Re: Tutorial de Traceline (Fakemeta)
#2

Aportazo
BlackFur is offline
Old 11-18-2012, 10:20
el999gonzalo
This message has been deleted by Starsailor. Reason: nothing to do with the thread.
XINLEI
me too
Join Date: Jun 2011
Location: Colombian Coffee storage
Old 11-18-2012 , 11:43   Re: Tutorial de Traceline (Fakemeta)
#3

Buena Traduccion.

Si tienes tiempo puedes traducir tambien el tutorial de natives dinamicas/falsas.
XINLEI is offline
Rama-PH
Member
Join Date: Feb 2009
Location: Colegiales, Argentina
Old 11-18-2012 , 13:14   Re: Tutorial de Traceline (Fakemeta)
#4

Quote:
Originally Posted by XINLEI View Post
Buena Traduccion.

Si tienes tiempo puedes traducir tambien el tutorial de natives dinamicas/falsas.
Gracias.

Proximamente voy a traducir otros tutoriales, veré ese que me mecionaste.
Rama-PH is offline
Starsailor
horrible hahah
Join Date: Aug 2008
Location: Buenos Aires
Old 11-18-2012 , 16:14   Re: Tutorial de Traceline (Fakemeta)
#5

Quote:
Originally Posted by el999gonzalo View Post
kajkjksajksaas jkyo jugaba en svs asi , eran cheeeveres xD
Podes evitar hacer post sin sentido?.. o por lo menos lo que comentas que tenga relacion con el thread.

saludos.
__________________
Find my plugins here..

Ex - Spanish Moderator.
Starsailor is offline
Neeeeeeeeeel.-
Some Guy Yellin'
Join Date: Jul 2010
Location: Argentina
Old 11-18-2012 , 16:23   Re: Tutorial de Traceline (Fakemeta)
#6

Se agradece la traducción... y tampoco conocía el tutorial anterior. Creo que me servirá y es mas fácil leerlo en español
__________________
Neeeeeeeeeel.- is offline
Send a message via Skype™ to Neeeeeeeeeel.-
gladius
Veteran Member
Join Date: Jul 2008
Location: Santiago, Chile
Old 11-18-2012 , 18:49   Re: Tutorial de Traceline (Fakemeta)
#7

Ok lo traduciste, pero si tenemos dudas eres capaz de respondernos?, le puedes dar soporte a las consultas que tengamos sobre el tutorial o simplemente es una traducción?
__________________
Proyects
Kreedz Chile Mod [100%] (Fixing some details).

gladius is offline
Send a message via MSN to gladius Send a message via Skype™ to gladius
DJHD!
Veteran Member
Join Date: Dec 2009
Location: Santiago, Chile
Old 11-27-2012 , 01:02   Re: Tutorial de Traceline (Fakemeta)
#8

Excelente tutorial habían varios puntos que no tenia bien entendidos gracias.
__________________
Quote:
Originally Posted by XINLEI View Post
Porque rocccos trata de ser el metalicross que nunca va a poder ser.
DJHD! is offline
Send a message via MSN to DJHD!
BlackFur
BANNED
Join Date: Apr 2012
Location: RCL
Old 11-27-2012 , 20:33   Re: Tutorial de Traceline (Fakemeta)
#9

Taba testeando eso y como chequeo si el trace es tocado por alguein? asi quitarle vida como el laser.
BlackFur is offline
Rama-PH
Member
Join Date: Feb 2009
Location: Colegiales, Argentina
Old 12-05-2012 , 12:17   Re: Tutorial de Traceline (Fakemeta)
#10

Quote:
Originally Posted by gladius View Post
Ok lo traduciste, pero si tenemos dudas eres capaz de respondernos?, le puedes dar soporte a las consultas que tengamos sobre el tutorial o simplemente es una traducción?
No, no creo que esté lo suficientemente capacitado como para dar soporte al respecto. Si tienen alguna duda lo mejor es tratar de consultarlo en el tema original (aclarado al comienzo de este). Me pareció una buena colaboración el traducir esto ya que hay muchas personas que no hablan inglés, y a mi me resulta muy fácil.

Puse a prueba el tutorial, y me fue muy útil, aunque inclusive todavía tengo dudas acerca de ciertas cosas.

Vine acá para aprender y ayudar, aunque por ahora lo que más voy a poder hacer es aprender, si se malinterpreto, pido disculpas.
Rama-PH is offline
 



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 13:08.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode