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

[TUT] Entities: what they are and how to use them


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-16-2006 , 20:13   [TUT] Entities: what they are and how to use them
Reply With Quote #1

Before we begin, please be aware that this tutorial is aimed toward scripters of intermediate level that understand Pawn conceptually but are still sketchy when it comes to implementation. Beginners may get confused, and experts may find they already know all this.

An entity is basically anything in the game that can change. The map is not an entity - it is impossible to change. You can do something like put a spraypaint on it, but that's not changing the map per se; rather it simply paints another texture on the location you sprayed.

Lights, players, the bomb, weapons (when on the ground, or even while being held in some mods) and breakable glass are all examples of entities. But what is important about ent(ities -- from now on they will be abbreviated to 'ents')? As said above, they can change. This means you can modify gameplay or make the game look different with them.

One of the most basic things that must be learned about entities is how to spawn one. Throughout this tutorial, I will post both an engine and fakemeta method of doing things, so here is one example:

Code:
// Engine new Ent = create_entity("classname")

Code:
// Fakemeta new Ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"classname"))

Now what do we see here that I haven't explained? What is this "classname"? A classname is given to all ents to help the engine determine what it is. If we stopped reading this tutorial and went outside, looking at various things, a person walking by might be classname "human" (however players in game are classname "player"), a tree might be classname "tree", a car might be "func_car" (func_ since it's a usable entity or it serves a purpose) and a cat might be "monster_cat" (monster_ because it's an NPC that may or may not be hostile). What can we do with the classname? We can use it to implement game functions (if you name an ent "hostage_entity" then Counter-Strike will automatically assume it's a hostage) or we can search for it (using find_ent_by_class or similar functions) among other things.

An entity also has other values. These values, such as health, target, targetname, gravity, movetype, etc. are all defined in part of HLSDK called the "edict_t" structure. An edict is effectively the basis for an entity because of this.

If you have any experience with AMXX scripting, you've probably ran into the function set_user_health. You may not understand what it does, but you know it works. What it basically does is go into the player's edict_t structure and change the "health" value (which is actually a float, not an int) to whatever you specify. Let's look at how it actually implements this though. Let's say for example we want to set a player's health to 200.

In fun, it looks like this:
Code:
set_user_health(id,200)

But in engine/fakemeta, it looks like this:
Code:
// engine entity_set_float(id,EV_FL_health,200.0) // fakemeta set_pev(id,pev_health,200.0)

We obviously have more power this way. It looks much more confusing, but rather than simply making a "set_user_x" (where x is gravity, targetname, or what not) we have access to the entire edict_t structure (which links to the entvars structure, which is where all the information really is).

But what about this "entity_set_float"? There are 12 functions when it comes to engine and manipulating the entvars of an 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

Additionally, we have some other functions that do similar things:

entity_set_origin
entity_set_model
entity_set_size

Note that these are not the same as simply using entity_set_vector/string, as they actually notify the engine (not the module) of the changes.

We have similar functions in fakemeta, however there are only 2 that do the same thing as these:

pev
set_pev

Because there is only 2, we have to be much more careful with fakemeta, since we could accidentally pass a float when the pev expects an int, or something to that effect.

There are also other functions which can be executed through engfunc and dllfunc (as shown near the top with the new Ent = engfunc... bit).

But now, how can these be implemented? We've already seen above how we can avoid fun and instead use engine/fakemeta, but what are some other things we can do with ents?

Well, let's say we want to teleport a player to a spot on the map. The first thing we must understand about where we want to teleport them, is that the location will be a vector. Why? Because a vector is a 3 cell array that contain data that generally acts as an x,y,z axis. We must also understand that all vectors implemented with engine/fakemeta are floats. Here is an example of a vector:

Code:
// static vector Float:{0.0,1.0,2.0} // dynamic vector new Float:Vector[3]

Now, how is this relevant to setting a player's location? We must first look up how we set the entity's origin. After looking through the funcwiki we come across this:

entity_set_origin

So what do we do? First, we find out where we want to teleport the player. Let's say we want to teleport them to 50,-30,1000. We must first convert this to a vector:

Code:
new Float:Origin[3] = {50.0,-30.0,1000.0}

Then set their origin.

Code:
// engine entity_set_origin(id,Origin) // fakemeta engfunc(EngFunc_SetOrigin,id,Origin)

When creating an entity, one of the most important things is to set its owner. Say, for example, a player types "car" in their console which creates a car in front of them, that can only be used by them. This can be done by setting their owner, and then checking when the ent is used if the owner is the person using it. Here is an example:

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.") }

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.") }

With these examples, we went into a few things that we haven't before. First of all - solidity. When we boil water and steam floats up from it, if we put our hands through they do not get stopped after they touch the first water droplet. If go poke the nearest person, our finger will get stopped once it makes contact with them. This can be represented through solidity in the HL engine. There are 5 different solid types, which can be found here: http://www.amxmodx.org/funcwiki.php?...=3#const_solid

The one we used in this case was SOLID_TRIGGER, because we want the player to trigger a touch when they touch the car (even though it will still trigger on BBOX or BSP).

Another concept we have yet to go over is entity_set_size / engfunc(EngFunc_SetSize..., which allows you to set the size of an entity. This is important because without it, the ent's solidity will not matter. If the entity is 0 units on the x,y,z axis, then it is by definition SOLID_NOT, even if we set it to SOLID_BSP/_BBOX. No matter how big the model is, it's the size that really matters.

This is already way too long, so I'm going to end this here. If you have any questions about this or any way to improve upon it, feel free to post.

Additional information:

The list of current Engine (module) entvar types can be found here (and below it):
http://www.amxmodx.org/funcwiki.php?...#const_ent_int
and the list of current Fakemeta entvars can be found here:
http://www.amxmodx.org/funcwiki.php?go=module&id=16
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Zenith77
Veteran Member
Join Date: Aug 2005
Old 08-16-2006 , 21:07   Re: Entities: what they are and how to use them
Reply With Quote #2

You've become a tutorial beast Hawk! Although it didn't do anything for me, somebody new to HL scripting could well benefit from this .
__________________
Quote:
Originally Posted by phorelyph View Post
your retatred
Zenith77 is offline
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-16-2006 , 22:11   Re: Entities: what they are and how to use them
Reply With Quote #3

Quote:
Originally Posted by gangstatothecore View Post
youve done it again, once again Hawk has impressed me , good tutoriol man !!!!! How would you go about setting , lets
say the bomb, as the oriigon? because its constantly moving you cant just set vectors right?
Hi raphero,

you can set it the same way as any other entity. for something like the bomb though, you should run drop_to_floor on it, to make sure that whoever tries to defuse it can.

To find the bomb and move it to x,y,z:
Code:
    new Ent = find_ent_by_model(-1,"grenade","models/w_c4.mdl")     // if not found -- probably not planted     if(!Ent)         return         entity_set_origin(Ent,Float:{0.0,0.0,0.0})
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-16-2006 , 23:12   Re: Entities: what they are and how to use them
Reply With Quote #4

Quote:
Originally Posted by gangstatothecore View Post
Well I dont want to move the bomb , I want to set the bomb as an origon to use
find_sphere_class
ans search the sphere from the bomb ,to find players . So would I still Use vectors to do this ?
EDIT
Thanks for making the tutoriol on entities . Good job!
Well all you have to do is:

Code:
new Float:Origin[3],EntList[32] entity_get_vector(Ent,EV_VEC_origin,Origin) find_sphere_class(0,"player",50.0,EntList,32,Origin)

assuming Ent is the bomb. Or you can just do:

Code:
new EntList[32] find_sphere_class(Ent,"player",50.0,EntList,32)

If you don't have the bomb's ent id, you can do:

Code:
new Ent = find_ent_by_model(-1,"grenade","models/w_c4.mdl")
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
k007
BANNED
Join Date: Mar 2006
Location: bacon?
Old 08-17-2006 , 01:12   Re: Entities: what they are and how to use them
Reply With Quote #5

Your the man Hawk gj
k007 is offline
Send a message via MSN to k007
Cheap_Suit
Veteran Member
Join Date: May 2004
Old 08-17-2006 , 01:52   Re: Entities: what they are and how to use them
Reply With Quote #6

I've always wondered..

When creating an custom entity why must be the classname info_target? Or can be anything?
__________________
HDD fried, failed to backup files. Sorry folks, just don't have free time anymore. This is goodbye.
Cheap_Suit is offline
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-17-2006 , 10:40   Re: Entities: what they are and how to use them
Reply With Quote #7

Quote:
Originally Posted by Cheap_Suit View Post
I've always wondered..

When creating an custom entity why must be the classname info_target? Or can be anything?
It can technically be anything, but honestly I don't know why most people use info_target. I'm reasonably sure it's better to set the ent's classname to what you want after it's spawned, so that's probably why.
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Mark186
Junior Member
Join Date: Aug 2006
Old 08-25-2006 , 01:43   Re: Entities: what they are and how to use them
Reply With Quote #8

I have a question concerning creating models that appear at server/map start.
Is there something that can be registered in public plugin_init() that is not a command and is executed during map start?
Mark186 is offline
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-25-2006 , 11:24   Re: Entities: what they are and how to use them
Reply With Quote #9

Quote:
Originally Posted by Mark186 View Post
I have a question concerning creating models that appear at server/map start.
Is there something that can be registered in public plugin_init() that is not a command and is executed during map start?
Umm...

Code:
public plugin_init() {      new Ent = create_entity("info_target")      // do shit }
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Illusionist
Junior Member
Join Date: Aug 2006
Old 08-28-2006 , 05:12   Re: Entities: what they are and how to use them
Reply With Quote #10

Nice tutorial Hawk, I have a question though, using engine, how can I create 2 or more entities with the same command or function. For instance, how could I set clcmd "CmdSayCar" to spawn two cars instead of one? (this is not the best example but I'm hoping that you understand what I'm trying to ask)
Illusionist is offline
Reply


Thread Tools
Display Modes

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 06:50.


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