Absolute Beginners Guide to (CSQC) Hats

Discuss CSQC related programming.
Post Reply
OneManClan
Posts: 247
Joined: Sat Feb 28, 2009 2:38 pm
Contact:

Absolute Beginners Guide to (CSQC) Hats

Post by OneManClan »

Image
PREFACE
DISCLAIMER: I'm still figuring all this out, and I barely know what I'm doing, so apologies in advance for any inaccuracies in the following 'beginner friendly' explanations. Rather than have this sit on my hard drive until it's 'perfect' (ie never), and since the following method DOES ACTUALLY WORK, why not have it out there where it might be useful to someone now? This is a 'draft', and I'll be constantly editing it over the next week or so, as corrections and clarifications come in from those who know more than I. As always, a big thanks to the Gurus at #qc, especially Spike, who is responsible for much of the code below.
[Revision: March 26th 2015. Added details on how to position the hat in Blender so that it exports without needing further 'adjusting' in the code. Removed code which positioned the hat.]


INTRODUCTION
Ok this is a tutorial on 'hats', but the code below can of course be used to attach anything to an iqm. 'Hat's is just an easy way to refer to 'a model you attach to another model, which moves with that model'. And 'player' is a short hand way of saying 'the iqm we are attaching the hat to'. This code is made with multiplayer in mind, as it affects the local players view of *other* players - ie you can't see your own hat. The reason this is done in CSQC is because many (ugh ok, most) AGR players are still using older, non-iqm compatible clients, and CSQC offers the possibility of giving fte clients the 'goodies' while leaving the others unaffected.

WHAT DO I NEED?
1. Blender
2. A player model with a head bone. This means an iqm. Here's a link to Capn Bubs Classic Quake style improved models, which include a brilliant player Blender file, which has been rigged and fully animated! You can convert to iqm yourself using this easy to follow Absolute Beginners Guide to IQMs! :)


MAKING THE HAT
Firstly, let's make the hat. I think [Gurus: please advise] the best way is to load the player model into Blender, and position the model so that head bone [the tip? :? ] is at '0 0 0'. Use it to get the position, proportions and angles of hat right. When you're done, delete the player model. Note: the hat doesn't need a bone. Export it as an IQM. How? Use the Absolute Beginners Guide to IQMs. Once your hat looks good in Noesis (ie the export worked), lets get started.

CSQC IMPLEMENTATION
First we're going to need a new .entity

Code: Select all

.entity hat; // yes, a hat!
Now we precache it, and make our code detect when a player is on the screen:

Code: Select all

#define THE_PLAYER_MODEL "progs/whateveryourpathis/player.iqm"
#define THE_HAT_MODEL "progs/whateveryourpathis/hat.iqm"

void(float apilevel, string enginename, float engineversion) CSQC_Init =
{

 // precache the player and hat here
precache_model(THE_PLAYER_MODEL);
precache_model(THE_HAT_MODEL);


  // everytime an entity using player.iqm comes into view, send it to Hattify
deltalisten(THE_PLAYER_MODEL, Hattify, 0);

};
Now we need to spawn, attach, and move the hat with the player. This all happens in the Hattify function:

Code: Select all

float(float isnew) Hattify =
{
       // 'self' is the player
      
       // did the player iqm just come into view?
        if(isnew)
        { 
          /* code in these brackets runs once, every time self appears on the screen*/         
          self.hat = spawn();
          setmodel(self.hat, THE_HAT_MODEL);
          
         }

          /* code below this line runs every frame, until self leaves the screen */

          // find self's (ie the player.iqm) 'Head' bone, and put the hat there!
          setorigin(self.hat, gettaginfo(self, gettagindex (self, "Head")));

      
          // make hat turn and tilt based on self's angles
          self.hat.angles = vectoangles(v_forward, v_up );

          
          self.hat.renderflags = self.renderflags; // make it so player cant see their own hat 
          self.hat.drawmask = 1; // draw the hat!
      
        return TRUE;  // If this returns false, it means for deltalisten to ignore Hattify, and leave the player.iqm 'unprocessed' 

};
Now some housekeeping - we need to get rid of the hat entity when the player disappears. CSQC has a function called CSQC_Ent_Remove which automatically removes entities when they disappear off screen, however it only does so with entities created by ssqc, and the hat entity is pure csqc. The hat however is a .field of 'the entity which has the player model', so it can be accessed (and removed) that way:

Code: Select all

  // CSQC_Ent_Remove runs when a ssqc entity disappears off the screen
void()CSQC_Ent_Remove=
{

  // self has moved off screen, and is about to be removed() , but before we do, check if it has any hats!
if(self.hat) 
  remove(self.hat);

 // and *now* we remove the hatless self
 remove(self);

}; 

That's it!

Note: in this tutorial I put the hats code in a separate function 'Hattify' for simplicity sake. In my actual code, I included its functionality in a general function 'PlayerUpdate' that performs multiple tasks on players models. I tried to have a separate deltalisten call for the same mdl but there were issues, because multiple deltalistens for the same model caused weird conflicts.. ugh hard to explain.. lets just say 'it didnt work'..

[UPDATE (April 2015): to do: I'd like to make animating hats, (eg one of those propellerhead caps), I think its just a matter of self.hat.frame = 1;]

Possibly useful/interesting/related links:
Making TF2 hats
Another TF2 hats tutorial
Post Reply