Welcome, Guest! Login | Register

Custom Model Entity [Print this Article]
Posted by: X-0ut
Date posted: Apr 27 2003
User Rating: 5 out of 5.0
Number of views: 6844
Number of comments: 3
Description:
This is a tutorial on making a custom model entity. With this entity your mappers will be able to place models in their maps rather than using a cycler or however they have been doing it.
This entity has been designed to do a few extra's of which you could alter to do even more effects - in fact I encourage you to do so.
This is what the entity supports, loading of model ingame (duh), sequence animation and also movement (by following a target).
I will explain best I can what the entity does and have added comments to make things more readable, at the end of the tutorial I will also explain a few simple ways to use the entity.
Ok open up effects.h at the top of the file after the defines add this class declaration:
 CODE  

class CModel : public CPointEntity
{
public:
    void Spawn( void );
    void EXPORT Animate();
    void KeyValue( KeyValueData *pkvd );
    int m_sequence;
};

Pretty small huh? This entity is really so simple.
Next effects.cpp at the very bottom of the file we can start filling in our class, but first we need to include this define:
 CODE  

#define MODEL_FOLLOW_TARGET  2

The MODEL_FOLLOW_TARGET constant will be used in the entitys spawnflags, when its ticked by the mapper the entity will move with a target - I'll explain more on that later.
 CODE  

void CModel::Spawn( void )
{
    pev->solid  = SOLID_BBOX;
    pev->movetype  = MOVETYPE_NONE;
    pev->effects  = 0;
    pev->frame  = 0;

    PRECACHE_MODEL( (char *)STRING(pev->model) );
    SET_MODEL( ENT(pev), STRING(pev->model) );
    pev->size.x = pev->scale=255;
    pev->size.y = pev->scale;
    pev->size.z = pev->scale;  
    pev->sequence =m_sequence;

    SetThink(Animate);
    pev->nextthink = gpGlobals->time+0.5;
}

Basically all that happens in the spawn function is we get the entity ready to be used, by setting its collision type, precaching and setting the model, setting the starting animation frame and setting a call to animate in half a seconds time after spawn.
 CODE  

void CModel::KeyValue( KeyValueData *pkvd )
{
    if (FStrEq(pkvd->szKeyName, "anim"))
    {
                  m_sequence = atoi(pkvd->szValue);
                  pkvd->fHandled = TRUE;
    }
    else
                  CBaseEntity::KeyValue( pkvd );
}

This function parses in the entitys key and value that are created in the fgd, notice how m_sequence is filled with the value of szValue, thats the sequence to play which the mapper would choose.
 CODE  

void CModel::Animate()
{
    //set next think just a little in the future for our next frame//
    SetThink(Animate);
    pev->nextthink = gpGlobals->time+0.01;
   
    //if the model has a sequence then play it//
    pev->frame >255? pev->frame=0:pev->frame++;
                                                                                                                                                                              

    ///move with a target//
    if (FBitSet (pev->spawnflags, MODEL_FOLLOW_TARGET ) )
    {
         //find the models target//
         edict_t    *pentTarget = NULL;
         pentTarget = FIND_ENTITY_BY_TARGETNAME( pentTarget, STRING(pev->target)  );
         if(FNullEnt(pentTarget))
              return;

         //now move to that target//
         Vector tmp = VARS( pentTarget )->origin;
         UTIL_SetOrigin( pev, tmp );
         pev->angles = VARS(pentTarget)->angles;
  
    }
}

Thats the final piece of code for the model entity, lets just take a moment to go over what happens in that animate function.
Firstly we are setting the next call to the function to happen 1/100ths of a second in the future, next we check to see if the last frame of the animation has been played, if it has not we move on a frame, if it has we restart the sequence.
Lastly if the MODEL_FOLLOW_TARGET spawnflag is true (remember that from earlier?) the models target entity is found and its origin and angles are copied into the model - thats how the entity moves.
Well thats it for the coding, but we still need to alter your mods FGD to incorporate the entity, so open up your FGD and place the model entity at the bottom of the file:
 CODE  

////////////////////////////////
//       env_model           //
////////////////////////////////
@PointClass base(Target, Targetname) size(-20 -20 -20, 20 20 20)color(255 0 0) studio()  = env_model : "env_model"
[
    model(studio) : "Model"
    anim(integer) : "Animation Sequence" : 0
    spawnflags(flags) =
    [
                        2: "Follow Target" : 0
    ]
]

Notice in the spawnflags:
 CODE  

  2: "Follow Target" : 0

2 is the same value as our earlier defined constant MODEL_FOLLOW_TARGET - yes thats right, thats how we we check if any spawnflags are ticked.

Ok so now you have a new model entity but how do you use it? Well I'll show a couple of examples and I'll suggest a few ideas, the rest is down to your mappers imagination.

Setting up the entity couldnt be easier, all the mapper has to do to make a non moving model is place the entity in the map, choose a model, animation sequence and leave the Follow Target flag unchecked. You could use this for things like trees, bushes, parked cars, statues - its up to you.
Ok so I thought it was supposed to move your thinking... Thats right it can move, for the sake of convenience I'll presume your mapper allready knows how to setup such entitys as func_trains.
Right, so the mapper has a func_train setup, its moving how he wants it and everything is working nicely. So how do we attach the model entity? Easy!
Give the func_train a name, for example train1. Now look at the model entity's properties and you'll see it has a target parameter, in it put train1.
Thats it, your model now moves with the func_train, this could be usefull for quite a few effects, imagine you have a cutscene where you need a truck to block an area, or you want a helicopter to fly overhead and land on a helipad....
Its all down to imagination user posted image

Well thats it for the custom model entity, hope somebody finds it usefull and or learned something.

Rate This Article
This article is currently rated: 5 out of 5.0 (2 Votes)

You have to register to rate this article.
User Comments Showing comments 1-3

Posted By: combat on Sep 18 2003 at 21:22:36
Nice. Very well done.

Posted By: Deepflame on Oct 07 2003 at 16:17:13
A little side note, when you are using models like scientist.mdl you might notice they're looking to their right.
You can fix this by making it derived from CBaseAnimating, and putting SetBoneController( 0, 0 ) in the spawn function.

Posted By: -+Arcadian+- on Dec 25 2003 at 02:07:02
I give this tut a 5! yay

One other small detail though.. in effects.cpp after:
#define MODEL_FOLLOW_TARGET 2

you will need to put something like:

LINK_ENTITY_TO_CLASS(env_model,CModel);

that umm well... links the entity in the fgd to your CModel class.


You must register to post a comment. If you have already registered, you must login.

Latest Articles
3rd person View in Multiplayer
Half-Life 2 | Coding | Client Side Tutorials
How to enable it in HL2DM

By: cct | Nov 13 2006

Making a Camera
Half-Life 2 | Level Design
This camera is good for when you join a map, it gives you a view of the map before you join a team

By: slackiller | Mar 05 2006

Making a camera , Part 2
Half-Life 2 | Level Design
these cameras are working monitors that turn on when a button is pushed.

By: slackiller | Mar 04 2006

Storing weapons on ladder
Half-Life 2 | Coding | Snippets
like Raven Sheild or BF2

By: British_Bomber | Dec 24 2005

Implementation of a string lookup table
Half-Life 2 | Coding | Snippets
A string lookup table is a set of functions that is used to convert strings to pre-defined values

By: deathz0rz | Nov 13 2005


Latest Comments
knock knock
General | News
By: MIFUNE | Dec 31 2017
 
knock knock
General | News
By: omega | Dec 22 2016
 
knock knock
General | News
By: MIFUNE | Oct 10 2015
 
New HL HUD Message System
Half-Life | Coding | Shared Tutorials
By: chbrules | Dec 31 2011
 
knock knock
General | News
By: Whistler | Nov 05 2011
 
Particle Engine tutorial part 4
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 18 2010
 
Particle Engine tutorial part 2
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Particle Engine tutorial part 3
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Game Movement Series #2: Analog Jumping and Floating
Half-Life 2 | Coding | Shared Tutorials
By: mars3554 | Oct 26 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Deadpool | Aug 02 2009
 

Site Info
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (4 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!