Welcome, Guest! Login | Register

Rescaling Half-Life [Print this Article]
Posted by: omega
Date posted: Aug 31 2003
User Rating: 3.2 out of 5.0
Number of views: 9237
Number of comments: 4
Description: The Updated Way!
I've now updated this rescale tutorial, it should now REALLY be 100% complete =)

Thanks to Entropy for figuring out the stuff that i missed and didn't really care about (i ended up dropping mmxhl shortly after DOING this for it).

Note: Most of the steps are the same, however some of my older code is being changed to reflect entropy's fixes or simply because i felt like it. (heh)

Step #1:
You must create a new hulls.txt file for all your maps to be rebuilt with. I'll use mine as an example. It's designed for a 2:1 scale (50% of the original player size). Just compare the defines and the hull file and it should be pretty easy to figure out different scales.

valve compile tools version:
 CODE  

( 0 0 0 ) ( 0 0 0 )             // point hull, don't change this
(  -8  -8 -16 ) (  8  8 16 )    // standing player hull
( -16 -16 -16 ) ( 16 16 16 )    // 32x32x32 large hull
(  -8  -8  -9 ) (  8 8 9 )      // ducking player hull

zoner's tools version:
 CODE  

8 8 16
16 16 16
8 8 9

Step #2:
Now it's time for code.
We'll start with the server. I tend to do all my pmove editing inside the client project, so we'll cover that later.

First off, we need to change the defines in util.h. Search for VEC_HULL_MIN and you'll find a block of defines like the block below. The sizes here go with a half size rescale (as mentioned above). You'll need to calculate your boxes and hulls yourself for differing scales.
Note: the standing hull's HEIGHT is different from the hullfile, it doesn't HAVE to be (it can be identical) i just kept it this way so its identical to HLDM, except 50% smaller.
 CODE (C++) 

//change these to be named  however you want. MELEE is the 64x64x64 hull. (now 32x32x32)
#define WORLD_HULL_POINT        0 //point hull
#define WORLD_HULL_GIRLS        1 //player hull
#define WORLD_HULL_ADULT        3 //crouch hull
#define WORLD_HULL_MELEE        2 //large hull


#define PLAYER_HULL_POINT       2 //point hull
#define PLAYER_HULL_GIRLS       0 //player hull
#define PLAYER_HULL_ADULT       1 //crouch hull
#define PLAYER_HULL_MELEE       3 //large hull


#define VEC_HULL_MIN            Vector(-8, -8, -18)
#define VEC_HULL_MAX            Vector( 8,  8,  18)
#define VEC_DUCK_HULL_MIN       Vector(-8, -8, -9 )
#define VEC_DUCK_HULL_MAX       Vector( 8,  8,  9 )
#define VEC_HUMAN_HULL_MIN      Vector( -8, -8, 0 )
#define VEC_HUMAN_HULL_MAX      Vector( 8, 8, 36 )
#define VEC_HUMAN_HULL_DUCK     Vector( 8, 8, 18 )
#define VEC_VIEW                Vector( 0, 0, 14 )
#define VEC_DUCK_VIEW           Vector( 0, 0, 6 )


UNDONE: You don't need to call UTIL_SetSize in CmdStart() or CmdEnd() in client.cpp

Open up world.cpp
Find CWorld::Spawn(), place this above it:
 CODE (C++) 

    extern "C" int g_model_hulls_fixed;

now add
 CODE (C++) 
 
    g_model_hulls_fixed = 0; // New map - make sure all the models get fixed again

INSIDE CWorld::Spawn, i placed it at the bottom of the function.

open up client.cpp and find GetHullBounds; do this:
 CODE (C++) 

int GetHullBounds( int hullnumber, float *mins, float *maxs )
{  
    int iret = 0;
    switch ( hullnumber )  
    {  
    case PLAYER_HULL_POINT:  
        mins[0] = mins[1] = mins[2] = 0;
        maxs[0] = maxs[1] = maxs[2] = 0;
        iret = 1;
        break;
    case PLAYER_HULL_GIRLS:  
        mins[0] = mins[1] = -8;mins[2] = -18;
        maxs[0] = maxs[1] = -8;maxs[2] = 18;
        iret = 1;
        break;
    case PLAYER_HULL_ADULT:  
        mins[0] = mins[1] = -8;mins[2] = -9;
        maxs[0] = maxs[1] = 8;maxs[2] = 9;
        iret = 1;
        break;
    case PLAYER_HULL_MELEE:  
        mins[0] = mins[1] = mins[2] = -16;
        maxs[0] = maxs[1] = maxs[2] = 16;
        iret = 1;
        break;
    }      
    return iret;
   
}

Thats it for the Server-Side, now for the client.

Step #3:
I got this next little code snippet from Adrian, so thank him. =)
Open up StudioModelRenderer.cpp, and take a look at StudioSetupBones() (near the middle of the file). You'll need to scale down each part of the bone matrix. You need to do it for all twelve array elements (three sizes, four parameters for each), like this:
IMPORTANT: This is only VISUAL. I cannot stress this enough, this only VISUALLY makes the models smaller; if you rely on hitboxes, they will NOT be scaled down on the server (where the damage happens!)
I recommend you scale models properly, and omit this change; if your mod doesn't require hitboxes, and instead uses the full bounding box, its okay.

 CODE (C++) 

    if (pbones[i].parent == -1)  
    {  
       
        // scale every model down to half size, since thats what we're scaling to using the defined sizes.  
        for (int j=0;j<3; j++)  
        {
            bonematrix[j][0] *= 0.5;
            bonematrix[j][1] *= 0.5;
            bonematrix[j][2] *= 0.5;
            bonematrix[j][3] *= 0.5;
        }        
    }
    if ( IEngineStudio.IsHardware() )



Step #4:
You now need to head over to cdll_int.cpp and modify GetHullBounds(). Make it look something like this. (or just like this if you're a copy and paster!)
 CODE (C++) 

//omega - rescale, hulls
#define PLAYER_HULL_POINT   2
#define PLAYER_HULL_GIRLS   0
#define PLAYER_HULL_ADULT   1
#define PLAYER_HULL_MELEE   3
int DLLEXPORT HUD_GetHullBounds( int hullnumber, float *mins, float *maxs )
{  
        int iret = 0;
       
        switch ( hullnumber )  
        {  
        case PLAYER_HULL_POINT:  
            mins[0] = mins[1] = mins[2] = 0;
            maxs[0] = maxs[1] = maxs[2] = 0;
            iret = 1;
            break;
        case PLAYER_HULL_GIRLS:  
            mins[0] = mins[1] = -8; mins[2] = -18;
            maxs[0] = maxs[1] = -8; maxs[2] = 18;
            iret = 1;
            break;
        case PLAYER_HULL_ADULT:  
            mins[0] = mins[1] = -8; mins[2] = -9;
            maxs[0] = maxs[1] = 8;  maxs[2] = 9;
            iret = 1;
            break;
        case PLAYER_HULL_MELEE:  
            mins[0] = mins[1] = mins[2] = -16;
            maxs[0] = maxs[1] = maxs[2] = 16;
            iret = 1;
            break;
        }      
        return iret;
}


Step #5:
Pull up hud_msg.cpp
add this above Msgfunc_ResetHUD:
 CODE (C++) 

    extern "C" int g_model_hulls_fixed;

now add this, INSIDE Msgfunc_ResetHUD:
 CODE (C++) 
 
    //rescale stuff
    g_model_hulls_fixed = 0;



Step #6:
For the final series of edits (yay!), we need to adjust the player's physics. Open up pm_shared.c in either the server or the client (the file is mirrored in both, so it doesn't matter which).

The first step will be to modify the defines near the top to reflect the changes we defined earlier, for heights and so forth:

 CODE (C++) 

#define VEC_HULL_MIN        -18
#define VEC_HULL_MAX        18
#define VEC_DUCK_HULL_MIN   -9
#define VEC_DUCK_HULL_MAX   9
#define VEC_DUCK_VIEW       6
#define VEC_VIEW            14


Step #7
PM_UpdateClipBox is very important because the *trace* boxes get wiped over. If you skip this step, your trace boxes will remain the standard size on the client, causing no end of grief.

This code is actually from one of my other mods. i'm copy and pasting it as i have it, you'll have to change it to reflect yours. i'm only modifying PARTS of it (the numerical values).

Enter both Entropy's omegafied code, and a modified version of my old PM_UpdateClipBox function:
NOTE:You'll need to include com_model.h, so make sure you wipe out any struct at the top of pm_shared.c thats been duplicated from com_model.h as well.
 CODE (C++) 

int g_model_hulls_fixed = 0;
#define WORLD_HULL_POINT    0
#define WORLD_HULL_GIRLS    1
#define WORLD_HULL_ADULT    3
#define WORLD_HULL_MELEE    2
#define PLAYER_HULL_POINT   2
#define PLAYER_HULL_GIRLS   0
#define PLAYER_HULL_ADULT   1
#define PLAYER_HULL_MELEE   3
//comment for tutorial: HULL_GIRLS is normal player, HULL_ADULT is player ducking, and HULL_MELEE is the old LARGE Hull
//omega - clipbox update
void PM_UpdateClipBox( void )
{
    vec3_t POINT_MIN;
    vec3_t POINT_MAX;
    vec3_t GIRLS_MIN;
    vec3_t GIRLS_MAX;
    vec3_t ADULT_MIN;
    vec3_t ADULT_MAX;
    vec3_t MELEE_MIN;
    //renamed the large hull, and resized it for melee attacks; so it doesn't trace as big.  
    vec3_t MELEE_MAX;
    POINT_MIN[0] = POINT_MIN[1] = POINT_MIN[2] = 0;
    POINT_MAX[0] = POINT_MAX[1] = POINT_MAX[2] = 0;
    GIRLS_MIN[0] = -8;  GIRLS_MIN[1] = -8;  GIRLS_MIN[2] = -18;
    GIRLS_MAX[0] = 8;   GIRLS_MAX[1] = 8;   GIRLS_MAX[2] = 18;
    ADULT_MIN[0] = -8;  ADULT_MIN[1] = -8;  ADULT_MIN[2] = -9;
    ADULT_MAX[0] = 8;   ADULT_MAX[1] = 8;   ADULT_MAX[2] = 9;
    MELEE_MIN[0] = -16; MELEE_MIN[1] = -16; MELEE_MIN[2] = -16;
    MELEE_MAX[0] = 16;  MELEE_MAX[1] = 16;  MELEE_MAX[2] = 16;
   
    VectorCopy(POINT_MIN, pmove->player_mins[PLAYER_HULL_POINT]);//override point  
    VectorCopy(POINT_MAX, pmove->player_maxs[PLAYER_HULL_POINT]);//i detect an error!  
    VectorCopy(GIRLS_MIN, pmove->player_mins[PLAYER_HULL_GIRLS]);//girls/boys-mins  
    VectorCopy(GIRLS_MAX, pmove->player_maxs[PLAYER_HULL_GIRLS]);//girls/boys-maxs  
    VectorCopy(ADULT_MIN, pmove->player_mins[PLAYER_HULL_ADULT]);//adults-mins  
    VectorCopy(ADULT_MAX, pmove->player_maxs[PLAYER_HULL_ADULT]);//adults-maxs  
    VectorCopy(MELEE_MIN, pmove->player_mins[PLAYER_HULL_MELEE]);//melee-mins  
    VectorCopy(MELEE_MAX, pmove->player_maxs[PLAYER_HULL_MELEE]);//melee-maxs
}
//rescale fixes
model_t * g_modelarray = NULL;
void PM_FixModelHulls()
{  
    int model;
   
    vec3_t POINT_MIN;
    vec3_t POINT_MAX;
    vec3_t GIRLS_MIN;
    vec3_t GIRLS_MAX;
    vec3_t ADULT_MIN;
    vec3_t ADULT_MAX;
    vec3_t MELEE_MIN;
    //renamed the large hull, and resized it for melee attacks;
    so it doesn't trace as big.  vec3_t MELEE_MAX;
    POINT_MIN[0] = POINT_MIN[1] = POINT_MIN[2] = 0;
    POINT_MAX[0] = POINT_MAX[1] = POINT_MAX[2] = 0;
    GIRLS_MIN[0] = -8; GIRLS_MIN[1] = -8;GIRLS_MIN[2] = -18;
    GIRLS_MAX[0] = 8;   GIRLS_MAX[1] = 8;   GIRLS_MAX[2] = 18;
    ADULT_MIN[0] = -8;  ADULT_MIN[1] = -8;  ADULT_MIN[2] = -9;
    ADULT_MAX[0] = 8;   ADULT_MAX[1] = 8;   ADULT_MAX[2] = 9;
    MELEE_MIN[0] = -16; MELEE_MIN[1] = -16; MELEE_MIN[2] = -16;
    MELEE_MAX[0] = 16;  MELEE_MAX[1] = 16;  MELEE_MAX[2] = 16;
   
    // Special case for the world model, since its name doesn't start with '*'  
    // It is only the first element of the models array for the first map.  
    // It is always pmove->physent[0], though  
    if (!g_modelarray)
        g_modelarray = pmove->physents[0].model;


    VectorCopy(POINT_MIN, pmove->physents[0].model->hulls[WORLD_HULL_POINT].clip_mins); //override point  
    VectorCopy(POINT_MAX, pmove->physents[0].model->hulls[WORLD_HULL_POINT].clip_maxs); //i detect an error  
    VectorCopy(GIRLS_MIN, pmove->physents[0].model->hulls[WORLD_HULL_GIRLS].clip_mins); //girls/boys-mins  
    VectorCopy(GIRLS_MAX, pmove->physents[0].model->hulls[WORLD_HULL_GIRLS].clip_maxs); //girls/boys-maxs  
    VectorCopy(ADULT_MIN, pmove->physents[0].model->hulls[WORLD_HULL_ADULT].clip_mins); //adults-mins  
    VectorCopy(ADULT_MAX, pmove->physents[0].model->hulls[WORLD_HULL_ADULT].clip_maxs); //adults-maxs  
    VectorCopy(MELEE_MIN, pmove->physents[0].model->hulls[WORLD_HULL_MELEE].clip_mins); //melee-mins  
    VectorCopy(MELEE_MAX, pmove->physents[0].model->hulls[WORLD_HULL_MELEE].clip_maxs); //melee-maxs    
   
    // All the BSP models other than the world have names in the format "*%d"  
    // Max # of models (of all types) assumed to be 512  for (model = 0; model < 1024; model++)
    {  
        if (pmove->physents[0].model[model].name[0] == '*')  
        {
            VectorCopy(POINT_MIN, g_modelarray[model].hulls[WORLD_HULL_POINT].clip_mins);//override point        
            VectorCopy(POINT_MAX, g_modelarray[model].hulls[WORLD_HULL_POINT].clip_maxs);//i detect an error        
            VectorCopy(GIRLS_MIN, g_modelarray[model].hulls[WORLD_HULL_GIRLS].clip_mins);//girls/boys-mins        
            VectorCopy(GIRLS_MAX, g_modelarray[model].hulls[WORLD_HULL_GIRLS].clip_maxs);//girls/boys-maxs        
            VectorCopy(ADULT_MIN, g_modelarray[model].hulls[WORLD_HULL_ADULT].clip_mins);//adults-mins        
            VectorCopy(ADULT_MAX, g_modelarray[model].hulls[WORLD_HULL_ADULT].clip_maxs);//adults-maxs        
            VectorCopy(MELEE_MIN, g_modelarray[model].hulls[WORLD_HULL_MELEE].clip_mins);//melee-mins        
            VectorCopy(MELEE_MAX, g_modelarray[model].hulls[WORLD_HULL_MELEE].clip_maxs);//melee-maxs  
        }
    }
}

Finally, you need to call PM_UpdateClipBox() and PM_FixModelHulls() down in PM_Move() right before PM_PlayerMove, like this:
 CODE (C++) 
 
    //omega clipbox update  
    PM_UpdateClipBox();
    if (!g_model_hulls_fixed)  
    {  
        PM_FixModelHulls();
        g_model_hulls_fixed = 1;
    }  
    PM_PlayerMove( ( server != 0 ) ? true : false );


Step #8:
There is no step 8! You're done! =)
You'll likely want to scale speeds and stuff down, but you can do that on your own. I hardcoded all of mine in input.cpp, but it can be done in the physics code, as well.

Optional:
You may want to do this (i did).
open up client.cpp, go to SetupVisibility, and change the part that calcs the view offset to simply this:
 CODE (C++) 

    if ( pView->v.flags & FL_DUCKING )  
        org = pView->v.origin + VEC_DUCK_VIEW;
    else  
        org = pView->v.origin + VEC_VIEW;


Rate This Article
This article is currently rated: 3.2 out of 5.0 (6 Votes)

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

Posted By: InternetNightmare on May 01 2004 at 17:31:44
void PM_FixModelHulls()
{
int model;

vec3_t POINT_MIN

Make it int model=0; Or it will crash

Posted By: omega on May 01 2004 at 18:29:13
no it won't.

that model integer it isn't even used, you can take that declaration out entirely.Edited by omega on May 01 2004, 18:29:39

Posted By: cct on May 07 2004 at 18:23:04
what u mean with
and stuff?

Posted By: christoph on Nov 12 2007 at 20:14:45
if anyone is interested in a fix for this tutorial just pm me or post here


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: 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
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Persuter | Aug 02 2009
 

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

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!