1 /*
2 ===========================================================================
3 Copyright (C) 2000-2006 Tim Angus
4
5 This file is part of Tremulous.
6
7 Tremulous is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Tremulous is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Tremulous; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 // cg_attachment.c -- an abstract attachment system
24
25 #include "cg_local.h"
26
27 /*
28 ===============
29 CG_AttachmentPoint
30
31 Return the attachment point
32 ===============
33 */
CG_AttachmentPoint(attachment_t * a,vec3_t v)34 qboolean CG_AttachmentPoint( attachment_t *a, vec3_t v )
35 {
36 centity_t *cent;
37
38 if( !a )
39 return qfalse;
40
41 // if it all breaks, then use the last point we know was correct
42 VectorCopy( a->lastValidAttachmentPoint, v );
43
44 switch( a->type )
45 {
46 case AT_STATIC:
47 if( !a->staticValid )
48 return qfalse;
49
50 VectorCopy( a->origin, v );
51 break;
52
53 case AT_TAG:
54 if( !a->tagValid )
55 return qfalse;
56
57 AxisCopy( axisDefault, a->re.axis );
58 CG_PositionRotatedEntityOnTag( &a->re, &a->parent,
59 a->model, a->tagName );
60 VectorCopy( a->re.origin, v );
61 break;
62
63 case AT_CENT:
64 if( !a->centValid )
65 return qfalse;
66
67 if( a->centNum == cg.predictedPlayerState.clientNum )
68 {
69 // this is smoother if it's the local client
70 VectorCopy( cg.predictedPlayerState.origin, v );
71 }
72 else
73 {
74 cent = &cg_entities[ a->centNum ];
75 VectorCopy( cent->lerpOrigin, v );
76 }
77 break;
78
79 case AT_PARTICLE:
80 if( !a->particleValid )
81 return qfalse;
82
83 if( !a->particle->valid )
84 {
85 a->particleValid = qfalse;
86 return qfalse;
87 }
88 else
89 VectorCopy( a->particle->origin, v );
90 break;
91
92 default:
93 CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" );
94 break;
95 }
96
97 if( a->hasOffset )
98 VectorAdd( v, a->offset, v );
99
100 VectorCopy( v, a->lastValidAttachmentPoint );
101
102 return qtrue;
103 }
104
105 /*
106 ===============
107 CG_AttachmentDir
108
109 Return the attachment direction
110 ===============
111 */
CG_AttachmentDir(attachment_t * a,vec3_t v)112 qboolean CG_AttachmentDir( attachment_t *a, vec3_t v )
113 {
114 vec3_t forward;
115 centity_t *cent;
116
117 if( !a )
118 return qfalse;
119
120 switch( a->type )
121 {
122 case AT_STATIC:
123 return qfalse;
124 break;
125
126 case AT_TAG:
127 if( !a->tagValid )
128 return qfalse;
129
130 VectorCopy( a->re.axis[ 0 ], v );
131 break;
132
133 case AT_CENT:
134 if( !a->centValid )
135 return qfalse;
136
137 cent = &cg_entities[ a->centNum ];
138 AngleVectors( cent->lerpAngles, forward, NULL, NULL );
139 VectorCopy( forward, v );
140 break;
141
142 case AT_PARTICLE:
143 if( !a->particleValid )
144 return qfalse;
145
146 if( !a->particle->valid )
147 {
148 a->particleValid = qfalse;
149 return qfalse;
150 }
151 else
152 VectorCopy( a->particle->velocity, v );
153 break;
154
155 default:
156 CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" );
157 break;
158 }
159
160 VectorNormalize( v );
161 return qtrue;
162 }
163
164 /*
165 ===============
166 CG_AttachmentAxis
167
168 Return the attachment axis
169 ===============
170 */
CG_AttachmentAxis(attachment_t * a,vec3_t axis[3])171 qboolean CG_AttachmentAxis( attachment_t *a, vec3_t axis[ 3 ] )
172 {
173 centity_t *cent;
174
175 if( !a )
176 return qfalse;
177
178 switch( a->type )
179 {
180 case AT_STATIC:
181 return qfalse;
182 break;
183
184 case AT_TAG:
185 if( !a->tagValid )
186 return qfalse;
187
188 AxisCopy( a->re.axis, axis );
189 break;
190
191 case AT_CENT:
192 if( !a->centValid )
193 return qfalse;
194
195 cent = &cg_entities[ a->centNum ];
196 AnglesToAxis( cent->lerpAngles, axis );
197 break;
198
199 case AT_PARTICLE:
200 return qfalse;
201 break;
202
203 default:
204 CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" );
205 break;
206 }
207
208 return qtrue;
209 }
210
211 /*
212 ===============
213 CG_AttachmentVelocity
214
215 If the attachment can have velocity, return it
216 ===============
217 */
CG_AttachmentVelocity(attachment_t * a,vec3_t v)218 qboolean CG_AttachmentVelocity( attachment_t *a, vec3_t v )
219 {
220 if( !a )
221 return qfalse;
222
223 if( a->particleValid && a->particle->valid )
224 {
225 VectorCopy( a->particle->velocity, v );
226 return qtrue;
227 }
228 else if( a->centValid )
229 {
230 centity_t *cent = &cg_entities[ a->centNum ];
231
232 VectorCopy( cent->currentState.pos.trDelta, v );
233 return qtrue;
234 }
235
236 return qfalse;
237 }
238
239 /*
240 ===============
241 CG_AttachmentCentNum
242
243 If the attachment has a centNum, return it
244 ===============
245 */
CG_AttachmentCentNum(attachment_t * a)246 int CG_AttachmentCentNum( attachment_t *a )
247 {
248 if( !a || !a->centValid )
249 return -1;
250
251 return a->centNum;
252 }
253
254 /*
255 ===============
256 CG_Attached
257
258 If the attachment is valid, return qtrue
259 ===============
260 */
CG_Attached(attachment_t * a)261 qboolean CG_Attached( attachment_t *a )
262 {
263 if( !a )
264 return qfalse;
265
266 return a->attached;
267 }
268
269 /*
270 ===============
271 CG_AttachToPoint
272
273 Attach to a point in space
274 ===============
275 */
CG_AttachToPoint(attachment_t * a)276 void CG_AttachToPoint( attachment_t *a )
277 {
278 if( !a || !a->staticValid )
279 return;
280
281 a->type = AT_STATIC;
282 a->attached = qtrue;
283 }
284
285 /*
286 ===============
287 CG_AttachToCent
288
289 Attach to a centity_t
290 ===============
291 */
CG_AttachToCent(attachment_t * a)292 void CG_AttachToCent( attachment_t *a )
293 {
294 if( !a || !a->centValid )
295 return;
296
297 a->type = AT_CENT;
298 a->attached = qtrue;
299 }
300
301 /*
302 ===============
303 CG_AttachToTag
304
305 Attach to a model tag
306 ===============
307 */
CG_AttachToTag(attachment_t * a)308 void CG_AttachToTag( attachment_t *a )
309 {
310 if( !a || !a->tagValid )
311 return;
312
313 a->type = AT_TAG;
314 a->attached = qtrue;
315 }
316
317 /*
318 ===============
319 CG_AttachToParticle
320
321 Attach to a particle
322 ===============
323 */
CG_AttachToParticle(attachment_t * a)324 void CG_AttachToParticle( attachment_t *a )
325 {
326 if( !a || !a->particleValid )
327 return;
328
329 a->type = AT_PARTICLE;
330 a->attached = qtrue;
331 }
332
333 /*
334 ===============
335 CG_SetAttachmentPoint
336 ===============
337 */
CG_SetAttachmentPoint(attachment_t * a,vec3_t v)338 void CG_SetAttachmentPoint( attachment_t *a, vec3_t v )
339 {
340 if( !a )
341 return;
342
343 VectorCopy( v, a->origin );
344 a->staticValid = qtrue;
345 }
346
347 /*
348 ===============
349 CG_SetAttachmentCent
350 ===============
351 */
CG_SetAttachmentCent(attachment_t * a,centity_t * cent)352 void CG_SetAttachmentCent( attachment_t *a, centity_t *cent )
353 {
354 if( !a || !cent )
355 return;
356
357 a->centNum = cent->currentState.number;
358 a->centValid = qtrue;
359 }
360
361 /*
362 ===============
363 CG_SetAttachmentTag
364 ===============
365 */
CG_SetAttachmentTag(attachment_t * a,refEntity_t parent,qhandle_t model,char * tagName)366 void CG_SetAttachmentTag( attachment_t *a, refEntity_t parent,
367 qhandle_t model, char *tagName )
368 {
369 if( !a )
370 return;
371
372 a->parent = parent;
373 a->model = model;
374 strncpy( a->tagName, tagName, MAX_STRING_CHARS );
375 a->tagValid = qtrue;
376 }
377
378 /*
379 ===============
380 CG_SetAttachmentParticle
381 ===============
382 */
CG_SetAttachmentParticle(attachment_t * a,particle_t * p)383 void CG_SetAttachmentParticle( attachment_t *a, particle_t *p )
384 {
385 if( !a )
386 return;
387
388 a->particle = p;
389 a->particleValid = qtrue;
390 }
391
392 /*
393 ===============
394 CG_SetAttachmentOffset
395 ===============
396 */
CG_SetAttachmentOffset(attachment_t * a,vec3_t v)397 void CG_SetAttachmentOffset( attachment_t *a, vec3_t v )
398 {
399 if( !a )
400 return;
401
402 VectorCopy( v, a->offset );
403 a->hasOffset = qtrue;
404 }
405