TRADUCCIÓN DE ESTE POST DE HAWK552
http://forums.alliedmods.net/showthread.php?t=43321
Tutorial para scripters de nivel medio.
Una entidad es basicamente algo en el juego que puede cambiar. El mapa no es una entidad - es imposible cambiarlo. Puedes hacer algo como poner un logo en el, pero esto no cambia el mapa; simplemente pinta otra textura en donde tu pusiste el logo.
Luces, jugadores, la bomba, armas (cuando estan en el suelo o en su mano) y cristales rompibles son todos los ejemplos de entidades. Pero, ¿qué es importante sobre las ent?(idades -- apartir de ahora lo abreviaremos a "ents")
Como dice antes, pueden cambiar. Esto significa que puedes modificar el gameplay o modificar la jugabilidad.
Una de las cosas mas basicas que se deben aprender sobre las entidades, es, como crear una. Durante este tutorial, pondre el método con engine y fakemeta, aqui un ejemplo:
PHP Code:
// Engine
new Ent = create_entity("classname")
// Fakemeta
new Ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"classname"))
Ahora, ¿que vamos a ver que no haya explicado ya?. Que es "classname" ?
Un "classname" es dado a todas las entidades para ayudar al motor a determinar cual es cada una. Si paramos de leer este tutorial y vamos fuera, miramos varias cosas, una persona andando debe tener el classname "humano" (aunque los jugadores en el juego tienen el classname "player"), un arbol debe tener el classname "arbol", un coche debe ser "func_car" (func_ porque es una entidad usable o tiene un proposito) y un gato debe ser "monster_car" (monster_ porque es un NPC que puede, o no, ser violento). ¿Que hacemos con el classname ? Lo podemos usar para implementar funciones del juego (si llamas a una entidad "hostage_entity" counter-strike va a asumir que es un rehén) o podemos buscarla (usando find_ent_by_class o funciones similares) y muchas mas cosas.
Una entidad tiene tambien otros valores. Esto valores, como la vida, objetivo, nombre del objetivo, gravedad, tipo de movimiento, etc. estan todos definidos en una parte del HLSDK llamada estructura "edict_t". Un edict es la base para una entidad por este motivo.
Si tienes experiencia, habras usado probablemente la funcion set_user_health. Puedes no saber que hace, pero sabes que funciona. Lo que hace es basicamente ir a la estructura edict_t de los jugadores y cambiar el valor de la vida (que es actualmente un float, no un int) a el que tu especifiques. Veamos como implementamos esto. Digamos por ejemplo, que queremos poner la vida de un jugador en 200.
En fun, seria asi
PHP Code:
set_user_health(id,200)
Pero en engine/fakemeta, seria asi
PHP Code:
// engine
entity_set_float(id, EV_FL_health, 200.0)
// fakemeta
set_pev(id, pev_health, 200.0)
Obviamente tenemos mas poder de esta manera, Suena mucho mas confuso, pero es tan simple como hacer un "set_user_x" (donde x puede ser gravedad, nombre del objetivo..) tenemos acceso total a la estructura edict_t (la cual nos lleva a la estructura entvars, donde esta toda la informacion)
Pero, ¿que pasa con esta "entity_set_float"? Hay 12 funciones cuando llega a manipular el engine y las entvars de una ent:
entity_get_int
entity_get_float
entity_get_string
entity_get_vector
entity_get_edict
entity_get_byte
entity_set_int
entity_set_float
entity_set_string
entity_set_vector
entity_set_edict
entity_set_byte
Adicionalmente, tenemos otras funciones que hacen cosas parecidas:
entity_set_origin
entity_set_model
entity_set_size
Ten en cuenta que estas no son igual de simples que usando entity_set_vector/string, que actualmente notifican al motor (no al modulo) de los cambios).
Tenemos funciones similares en fakemeta, hay dos que hacen la mismo que las anteriores:
pev
set_pev
Como solo hay dos, debemos tener mas cuidado con fakemeta, porque podemos pasar accidentalmente un float cuando el pev espera un int, o cosas de este tipo.
Hay ademas otras funciones que pueden ser ejecutadas mediante engfunc y dllfunc (como mostre en el principio con el new Ent = engfunc...)
Pero ahora, ¿como las podemos implementar? Ya hemos visto como podemos evitar usar fun y usar en lugar de ello engine o fakemeta, pero que más podemos hacer con ents?
Bueno, digamos que queremos teletransportar a un jugador a una parte del mapa. Primero debemos entender que a donde lo queremos teletransportar, será un vector. Porque ? Porque un vector es un array de 3 celdas que contiene informacion que actua generalmente como las abcisas x, y, z. Debemos tambien entender que los vectores implementados con engine/fakemeta son floats. Aqui un ejemplo de un vector:
PHP Code:
// vector estatico
Float:{0.0,1.0,2.0}
// vector dinamico
new Float:Vector[3]
Ahora, como ponemos la localizacion de un jugador? Primero debemos mirar como ponemos el origen de las entidades. Despues de mirar en la funcwiki, tendremos algo asi:
entity_set_origin
Asi que, que hacemos? Primero, buscamos el lugar a donde queremos teletransportar a ese jugador. Digamos que lo queremos teletransportar a 50, -30, 1000. Primero debemos convertir esto en un vector
PHP Code:
new Float:Origin[3] = {50.0,-30.0,1000.0}
Depues ponerle su origen
PHP Code:
// engine
entity_set_origin(id, Origin)
// fakemeta
engfunc(EngFunc_SetOrigin, id, Origin)
Cuando creamos una entidad, una de las cosas mas importantes es setear su propietario. Digamos, por ejemplo, un jugador escribe "car" (coche in spanish ;p) en su consola y crea un coche delante de el, que puede ser usado unicamente por el. Esto puede ser hecho seteando su propietario, y despues comprobando que cuando la ent es usa cuando el propietario es la persona que la utiliza. Aqui un ejemplo:
PHP Code:
// engine
#include <amxmodx>
#include <amxmisc>
#include <engine>
new g_Classname[] = "func_car"
new g_Model[] = "models/car.mdl"
public plugin_init()
{
register_plugin("OMFG","HAX","LOL")
register_clcmd("say car","CmdSayCar")
register_touch(g_Classname,"player","TouchCar")
}
public plugin_precache()
precache_model(g_Model)
public CmdSayCar(id)
{
new Ent = create_entity("info_target")
entity_set_string(Ent,EV_SZ_classname,g_Classname)
entity_set_model(Ent,g_Model)
entity_set_int(Ent,EV_INT_solid,SOLID_TRIGGER)
entity_set_size(Ent,Float:{-50.0,-50.0,-50.0},Float:{50.0,50.0,50.0})
entity_set_edict(Ent,EV_ENT_owner,id)
}
public TouchCar(Ptd,Ptr)
{
new Owner = entity_get_edict(Ptd,EV_ENT_owner)
if(Owner != Ptr)
return
client_print(Ptr,print_chat,"You have used this car. Due to time purposes, I'm not going to add code beyond this.")
}
PHP Code:
// fakemeta
#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
new g_Classname[] = "func_car"
new g_Model[] = "models/car.mdl"
public plugin_init()
{
register_plugin("OMFG","HAX","LOL")
register_clcmd("say car","CmdSayCar")
register_forward(FM_Touch,"ForwardTouch")
}
public plugin_precache()
precache_model(g_Model)
public CmdSayCar(id)
{
new Ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
set_pev(Ent,pev_classname,g_Classname)
engfunc(EngFunc_SetModel,Ent,g_Model)
set_pev(Ent,pev_solid,SOLID_TRIGGER)
engfunc(EngFunc_SetSize,Ent,Float:{-50.0,-50.0,-50.0},Float:{50.0,50.0,50.0})
set_pev(Ent,pev_owner,id)
}
public ForwardTouch(Ptd,Ptr)
{
new Classname[33],Ent = Ptd,id = Ptr
pev(Ptd,pev_classname,Classname,32)
if(!equal(Classname,g_Classname))
{
Ent = Ptr
id = Ptd
pev(Ptr,pev_classname,Classname,32)
if(!equal(Classname,g_Classname))
return
}
new Owner = pev(Ent,pev_owner)
if(Owner != id)
return
client_print(id,print_chat,"You have used this car. Due to time purposes, I'm not going to add code beyond this.")
}
Con esto ejemplos, entramos en unas cosas que no vimos antes. Primero - solidos. Cuando hervimos agua y el vapor sube de ella, si podemos nuestras manos por medio, el vapor no parara hasta que toque la primera gota de agua. Si van a pinchar a la persona mas cercana, tu dedo se detendra cuandod haga contacto con ella. Esto puede ser representado mediante los solidos en el motor de HL. Hay 5 tipos diferentes de solidos, que pueden ser encontrados aqui:
http://www.amxmodx.org/funcwiki.php?...=3#const_solid
El usado en este caso fue SOLIT_TRIGGER, porque queremos que el jugador desencadene un "touch" cuando toca el coche.
Otro concepto que tenemos tambien es entity_set_size / engfunc(EngFunc_SetSize....., que te permite setear el tamaño de una entidad.
Esto es importante, porque sin el, el solido no importaria. Si la entidad es de 0 unidades en las abcisas x, y, z, entonces seria por definicion SOLIT_NOT, tambien si lo ponemos en SOLID_BSP/_BBOX. No hay problema sobre lo grande que sea el modelo, es el tamaño lo que realmente importa.
Saludos,
Javivi.
__________________