NOTE: Afaik, setattachment is only compatible with FTE and DP
PREFACE
There's already a very helpful page on the Quake Wiki, which pretty much covers all you need to know about setattachment, but for those who need more, here's my unapologetically handholding guide, for absolute beginners, and of course, for a future me who doesn't remember exactly how I got this working.
INTRODUCTION
Setattachment is a (ssqc) way to connect multiple models together so that they can appear as 'one model' but each body part can be controlled seperately. For this 'step by step' walkthrough we will make a model consisting of 3 parts: 'RobotLegs', 'RobotTorso', and 'Robothead'. Each body part will have its own thinks, but 'RobotTorso' and 'Robothead' will be 'child' entities, permanently connected to 'RobotLegs', the 'parent' entity.
PREPARING THE MODEL
1. In Blender, make a (crappy boxy test) model with 3 bodyparts, RobotLegs, RobotTorso, and Robothead. Keep the three as seperate objects (ie don't join them).
2. Make an armature, 3 bones "legs", "torso", and "head", and connect each bone to its respective mesh. [TIP: If it's a robot, check the weights (weight paint) to make sure that rotating one part has 0 influece on the adjoining part.]
3. Save the Blender file.
4. Export each body part with it's bone as a seperate iqm (using Salzmans iqm exporter). Note: This example doesn't need animations (leave the 'animations' field blank) TIP: Remember to scale the model up on Export (I've been using 8 with great results), otherwise you might have trouble seeing it in-game.
THE QUAKE C
Code: Select all
// declare the body parts
#define ROBOT_LEGS "progs/robot_legs.iqm"
#define ROBOT_TORSO "progs/robot_torso.iqm"
#define ROBOT_HEAD "progs/robot_head.iqm"
Code: Select all
// precache them
precache_model(ROBOT_LEGS);
precache_model(ROBOT_TORSO);
precache_model(ROBOT_HEAD );
Code: Select all
// The spawning
//spawn the parent entity (the one the others will attach to)
entity robot_legs= spawn();
setmodel (robot_legs, ROBOT_LEGS);
setorigin(robot_legs, where_you_want_it_to_spawn);
robot_legs.think = robot_legs_think;
robot_legs.nextthink = time + 1;
// spawn child entity 1: robot_torso
entity robot_torso= spawn();
setmodel (robot_torso, ROBOT_TORSO);
// attach entity 'robot_torso' to entity 'robot_legs', using the robot_torso bone/tag called 'torso'
setattachment (robot_torso, robot_legs, "torso");
robot_torso.think = robot_torso_think;
robot_torso.nextthink = time + 1;
// spawn the child entity 2: robot_head
entity robot_head = spawn();
setmodel (robot_head, ROBOT_HEAD);
// attach entity 'robot_head' to entity 'robot_torso', using the bone/tag called 'head'
setattachment (robot_head, robot_torso, "head"); // Q: should it attach to Robotlegs/the parent??
robot_head.think = robot_head_think;
robot_head.nextthink = time + 1;
7. When a child becomes 'setattached', it's origin becomes '0 0 0', and the parent becomes the childs .tag_entity. To get the parents origin, you can go:
Code: Select all
vector parent_origin = child.tag_entity.origin;
Code: Select all
// the parent
void() robot_legs_think=
{
// code for the Robotlegs
// origin is self.origin
}
// child
void() robot_torso_think=
{
// code for the robot_torso
// Note: self.origin is '0 0 0'
// To get robot_torso's origin:
float robot_torso_bone_number = gettagindex(self, "torso");
vector robot_torso_origin = gettaginfo(self, robot_torso_bone_number);
}