]> git.jsancho.org Git - lugaru.git/blob - Source/Skeleton.cpp
33f242282f319b0a7d9ae4abae59f0a21be2f9bf
[lugaru.git] / Source / Skeleton.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21
22 /**> HEADER FILES <**/
23 #include "Game.h"
24 #include "Skeleton.h"
25 #include "openal_wrapper.h"
26 #include "Animation.h"
27
28 extern float multiplier;
29 extern float gravity;
30 extern Skeleton testskeleton;
31 extern Terrain terrain;
32 extern Objects objects;
33 extern int environment;
34 extern float camerashake;
35 extern bool freeze;
36 extern int detail;
37 extern XYZ envsound[30];
38 extern float envsoundvol[30];
39 extern int numenvsounds;
40 extern float envsoundlife[30];
41 extern int tutoriallevel;
42
43 extern int whichjointstartarray[26];
44 extern int whichjointendarray[26];
45
46 extern bool visibleloading;
47
48 void dealloc2(void* param)
49 {
50     free(param);
51     param = 0;
52 }
53
54 enum {boneconnect, constraint, muscle};
55
56 void Muscle::DoConstraint(bool spinny)
57 {
58     static XYZ vel;
59     static XYZ midp;
60     static XYZ newpoint1, newpoint2;
61
62     static float oldlength;
63     static float relaxlength;
64
65     oldlength = length;
66
67     if (type != boneconnect)
68         relaxlength = findDistance(&parent1->position, &parent2->position);
69
70     if (type == boneconnect)
71         strength = 1;
72     if (type == constraint)
73         strength = 0;
74
75     if (strength < 0)
76         strength = 0;
77     if (strength > 1)
78         strength = 1;
79
80     length -= (length - relaxlength) * (1 - strength) * multiplier * 10000;
81     length -= (length - targetlength) * (strength) * multiplier * 10000;
82     if (strength == 0)
83         length = relaxlength;
84
85     if ((relaxlength - length > 0 && relaxlength - oldlength < 0) || (relaxlength - length < 0 && relaxlength - oldlength > 0))
86         length = relaxlength;
87
88     //if(!broken){
89     if (length < minlength)
90         length = minlength;
91     if (length > maxlength)
92         length = maxlength;
93     //}
94     /*
95     if(broken){
96     if(length<minlength*.6)length=minlength*.6;
97     if(length>maxlength*1.4)length=maxlength*1.4;
98     }
99     */
100     if (length == relaxlength)
101         return;
102
103     //Find midpoint
104     midp = (parent1->position * parent1->mass + parent2->position * parent2->mass) / (parent1->mass + parent2->mass);
105     //Find vector from midpoint to second vector
106     vel = parent2->position - midp;
107     //Change to unit vector
108     Normalise(&vel);
109     //Apply velocity change
110     newpoint1 = midp - vel * length * (parent2->mass / (parent1->mass + parent2->mass));
111     newpoint2 = midp + vel * length * (parent1->mass / (parent1->mass + parent2->mass));
112     if (!freeze && spinny) {
113         parent1->velocity = parent1->velocity + (newpoint1 - parent1->position) / multiplier / 4;
114         parent2->velocity = parent2->velocity + (newpoint2 - parent2->position) / multiplier / 4;
115     } else {
116         parent1->velocity = parent1->velocity + (newpoint1 - parent1->position);
117         parent2->velocity = parent2->velocity + (newpoint2 - parent2->position);
118     }
119     //Move child point to within certain distance of parent point
120     parent1->position = newpoint1;
121     parent2->position = newpoint2;
122 }
123
124 void Skeleton::FindForwardsfirst()
125 {
126     //Find forward vectors
127     CrossProduct(joints[forwardjoints[1]].position - joints[forwardjoints[0]].position, joints[forwardjoints[2]].position - joints[forwardjoints[0]].position, &forward);
128     Normalise(&forward);
129
130     CrossProduct(joints[lowforwardjoints[1]].position - joints[lowforwardjoints[0]].position, joints[lowforwardjoints[2]].position - joints[lowforwardjoints[0]].position, &lowforward);
131     Normalise(&lowforward);
132
133     //Special forwards
134     specialforward[0] = forward;
135     specialforward[1] = forward;
136     specialforward[2] = forward;
137     specialforward[3] = forward;
138     specialforward[4] = forward;
139
140 }
141 void Skeleton::FindForwards()
142 {
143     //Find forward vectors
144     CrossProduct(joints[forwardjoints[1]].position - joints[forwardjoints[0]].position, joints[forwardjoints[2]].position - joints[forwardjoints[0]].position, &forward);
145     Normalise(&forward);
146
147     CrossProduct(joints[lowforwardjoints[1]].position - joints[lowforwardjoints[0]].position, joints[lowforwardjoints[2]].position - joints[lowforwardjoints[0]].position, &lowforward);
148     Normalise(&lowforward);
149
150     //Special forwards
151     specialforward[0] = forward;
152
153     specialforward[1] = joints[jointlabels[rightshoulder]].position + joints[jointlabels[rightwrist]].position;
154     specialforward[1] = joints[jointlabels[rightelbow]].position - specialforward[1] / 2;
155     specialforward[1] += forward * .4;
156     Normalise(&specialforward[1]);
157     specialforward[2] = joints[jointlabels[leftshoulder]].position + joints[jointlabels[leftwrist]].position;
158     specialforward[2] = joints[jointlabels[leftelbow]].position - specialforward[2] / 2;
159     specialforward[2] += forward * .4;
160     Normalise(&specialforward[2]);
161
162     specialforward[3] = joints[jointlabels[righthip]].position + joints[jointlabels[rightankle]].position;
163     specialforward[3] = specialforward[3] / 2 - joints[jointlabels[rightknee]].position;
164     specialforward[3] += lowforward * .4;
165     Normalise(&specialforward[3]);
166     specialforward[4] = joints[jointlabels[lefthip]].position + joints[jointlabels[leftankle]].position;
167     specialforward[4] = specialforward[4] / 2 - joints[jointlabels[leftknee]].position;
168     specialforward[4] += lowforward * .4;
169     Normalise(&specialforward[4]);
170 }
171
172 float Skeleton::DoConstraints(XYZ *coords, float *scale)
173 {
174     static float friction = 1.5;
175     static float elasticity = .3;
176     static XYZ bounceness;
177     static XYZ oldpos[100];
178     static int numrepeats = 3;
179     static float groundlevel = .15;
180     static float soundvolume;
181     static int i, j, k, l, m;
182     static XYZ temp, start, end;
183     static XYZ terrainnormal;
184     static float r = .05;
185     static float r2 = .08;
186     static int whichhit;
187     //static int whichjointstart,whichjointend;
188     static float distance;
189     static float frictionness;
190     static XYZ terrainlight;
191     static int whichpatchx;
192     static int whichpatchz;
193     static float damage;
194     static bool freely;
195     static float tempmult;
196     static bool breaking;
197     breaking = 0;
198
199     damage = 0;
200
201     if (free) {
202         freetime += multiplier;
203
204         whichpatchx = coords->x / (terrain.size / subdivision * terrain.scale);
205         whichpatchz = coords->z / (terrain.size / subdivision * terrain.scale);
206
207         terrainlight = *coords;
208         objects.SphereCheckPossible(&terrainlight, 1);
209         /*
210         for(i=0; i<num_joints; i++){
211         oldpos[i]=joints[i].position;
212         }*/
213
214         //Add velocity
215         for (i = 0; i < num_joints; i++) {
216             //if(!isnormal(joints[i].velocity.x)||!isnormal(joints[i].velocity.y)||!isnormal(joints[i].velocity.z))joints[i].velocity=0;
217             joints[i].position = joints[i].position + joints[i].velocity * multiplier;
218             groundlevel = .15;
219             if (joints[i].label == head)
220                 groundlevel = .8;
221             if (joints[i].label == righthand || joints[i].label == rightwrist || joints[i].label == rightelbow)
222                 groundlevel = .2;
223             if (joints[i].label == lefthand || joints[i].label == leftwrist || joints[i].label == leftelbow)
224                 groundlevel = .2;
225             joints[i].position.y -= groundlevel;
226             //if(!joints[i].locked&&!broken)joints[i].velocity+=joints[i].velchange*multiplier*10*(500-longdead)/500;
227             joints[i].oldvelocity = joints[i].velocity;
228         }
229         tempmult = multiplier;
230         //multiplier/=numrepeats;
231         for (j = 0; j < numrepeats; j++) {
232             if (!joints[jointlabels[rightknee]].locked && !joints[jointlabels[righthip]].locked) {
233                 temp = joints[jointlabels[rightknee]].position - (joints[jointlabels[righthip]].position + joints[jointlabels[rightankle]].position) / 2;
234                 while (normaldotproduct(temp, lowforward) > -.1 && !sphere_line_intersection(&joints[jointlabels[righthip]].position, &joints[jointlabels[rightankle]].position, &joints[jointlabels[rightknee]].position, &r)) {
235                     joints[jointlabels[rightknee]].position -= lowforward * .05;
236                     if (spinny)
237                         joints[jointlabels[rightknee]].velocity -= lowforward * .05 / multiplier / 4;
238                     else
239                         joints[jointlabels[rightknee]].velocity -= lowforward * .05;
240                     joints[jointlabels[rightankle]].position += lowforward * .025;
241                     if (spinny)
242                         joints[jointlabels[rightankle]].velocity += lowforward * .025 / multiplier / 4;
243                     else
244                         joints[jointlabels[rightankle]].velocity += lowforward * .25;
245                     joints[jointlabels[righthip]].position += lowforward * .025;
246                     if (spinny)
247                         joints[jointlabels[righthip]].velocity += lowforward * .025 / multiplier / 4;
248                     else
249                         joints[jointlabels[righthip]].velocity += lowforward * .025;
250                     temp = joints[jointlabels[rightknee]].position - (joints[jointlabels[righthip]].position + joints[jointlabels[rightankle]].position) / 2;
251                 }
252             }
253             if (!joints[jointlabels[leftknee]].locked && !joints[jointlabels[righthip]].locked) {
254                 temp = joints[jointlabels[leftknee]].position - (joints[jointlabels[lefthip]].position + joints[jointlabels[leftankle]].position) / 2;
255                 while (normaldotproduct(temp, lowforward) > -.1 && !sphere_line_intersection(&joints[jointlabels[lefthip]].position, &joints[jointlabels[leftankle]].position, &joints[jointlabels[leftknee]].position, &r)) {
256                     joints[jointlabels[leftknee]].position -= lowforward * .05;
257                     if (spinny)
258                         joints[jointlabels[leftknee]].velocity -= lowforward * .05 / multiplier / 4;
259                     else
260                         joints[jointlabels[leftknee]].velocity -= lowforward * .05;
261                     joints[jointlabels[leftankle]].position += lowforward * .025;
262                     if (spinny)
263                         joints[jointlabels[leftankle]].velocity += lowforward * .025 / multiplier / 4;
264                     else
265                         joints[jointlabels[leftankle]].velocity += lowforward * .25;
266                     joints[jointlabels[lefthip]].position += lowforward * .025;
267                     if (spinny)
268                         joints[jointlabels[lefthip]].velocity += lowforward * .025 / multiplier / 4;
269                     else
270                         joints[jointlabels[lefthip]].velocity += lowforward * .025;
271                     temp = joints[jointlabels[leftknee]].position - (joints[jointlabels[lefthip]].position + joints[jointlabels[leftankle]].position) / 2;
272                 }
273             }
274
275             for (i = 0; i < num_joints; i++) {
276                 //joints[i].delay-=multiplier/1.5;
277                 if (joints[i].locked)
278                     if (!spinny)
279                         if (findLengthfast(&joints[i].velocity) > 320)
280                             joints[i].locked = 0;
281                 if (spinny)
282                     if (findLengthfast(&joints[i].velocity) > 600)
283                         joints[i].locked = 0;
284                 if (joints[i].delay > 0) {
285                     freely = 1;
286                     for (j = 0; j < num_joints; j++) {
287                         if (joints[j].locked)
288                             freely = 0;
289                     }
290                     if (freely)
291                         joints[i].delay -= multiplier * 3;
292                 }
293                 //if(joints[i].delay>0)
294                 //if(findLengthfast(&joints[i].velocity)>700&&joints[i].label!=head)joints[i].delay-=multiplier;
295             }
296
297             if (num_muscles)
298                 for (i = 0; i < num_muscles; i++) {
299                     //Length constraints
300                     //muscles[i].DoConstraint(broken);
301                     muscles[i].DoConstraint(spinny);
302                 }
303
304             for (i = 0; i < num_joints; i++) {
305                 //joints[i].delay-=multiplier/1.5;
306                 //Length constraints
307                 //Ground constraint
308                 groundlevel = 0;
309                 if (joints[i].position.y * (*scale) + coords->y < terrain.getHeight(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z) + groundlevel) {
310                     freefall = 0;
311                     friction = 1.5;
312                     if (joints[i].label == groin && !joints[i].locked && joints[i].delay <= 0) {
313                         joints[i].locked = 1;
314                         joints[i].delay = 1;
315                         if (tutoriallevel != 1 || id == 0) {
316                             emit_sound_at(landsound1, joints[i].position * (*scale) + *coords, 128.);
317                         }
318                         breaking = 1;
319                     }
320
321                     if (joints[i].label == head && !joints[i].locked && joints[i].delay <= 0) {
322                         joints[i].locked = 1;
323                         joints[i].delay = 1;
324                         if (tutoriallevel != 1 || id == 0) {
325                             emit_sound_at(landsound2, joints[i].position * (*scale) + *coords, 128.);
326                         }
327                     }
328
329                     terrainnormal = terrain.getNormal(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z);
330                     ReflectVector(&joints[i].velocity, &terrainnormal);
331                     bounceness = terrainnormal * findLength(&joints[i].velocity) * (abs(normaldotproduct(joints[i].velocity, terrainnormal)));
332                     if (!joints[i].locked)
333                         damage += findLengthfast(&bounceness) / 4000;
334                     if (findLengthfast(&joints[i].velocity) < findLengthfast(&bounceness))
335                         bounceness = 0;
336                     frictionness = abs(normaldotproduct(joints[i].velocity, terrainnormal)); //findLength(&bounceness)/findLength(&joints[i].velocity);
337                     joints[i].velocity -= bounceness;
338                     if (1 - friction * frictionness > 0)
339                         joints[i].velocity *= 1 - friction * frictionness;
340                     else
341                         joints[i].velocity = 0;
342
343                     if (tutoriallevel != 1 || id == 0)
344                         if (findLengthfast(&bounceness) > 8000 && breaking) {
345                             objects.model[k].MakeDecal(breakdecal, DoRotation(temp - objects.position[k], 0, -objects.yaw[k], 0), .4, .5, Random() % 360);
346                             Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, 1, 1, 1, 4, .2);
347                             //Sprite::MakeSprite(cloudsprite, joints[i].position*(*scale)+*coords,joints[i].velocity*.06, 1,1,1, 1, .2);
348                             breaking = 0;
349                             camerashake += .6;
350
351                             emit_sound_at(breaksound2, joints[i].position * (*scale) + *coords);
352
353                             envsound[numenvsounds] = *coords;
354                             envsoundvol[numenvsounds] = 64;
355                             envsoundlife[numenvsounds] = .4;
356                             numenvsounds++;
357                         }
358
359                     if (findLengthfast(&bounceness) > 2500) {
360                         Normalise(&bounceness);
361                         bounceness = bounceness * 50;
362                     }
363
364                     joints[i].velocity += bounceness * elasticity;
365
366                     if (findLengthfast(&joints[i].velocity) > findLengthfast(&joints[i].oldvelocity)) {
367                         bounceness = 0;
368                         joints[i].velocity = joints[i].oldvelocity;
369                     }
370
371
372                     if (joints[i].locked == 0)
373                         if (findLengthfast(&joints[i].velocity) < 1)
374                             joints[i].locked = 1;
375
376                     if (environment == snowyenvironment && findLengthfast(&bounceness) > 500 && terrain.getOpacity(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z) < .2) {
377                         terrainlight = terrain.getLighting(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z);
378                         Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, terrainlight.x, terrainlight.y, terrainlight.z, .5, .7);
379                         if (detail == 2)
380                             terrain.MakeDecal(bodyprintdecal, joints[i].position * (*scale) + *coords, .4, .4, 0);
381                     } else if (environment == desertenvironment && findLengthfast(&bounceness) > 500 && terrain.getOpacity(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z) < .2) {
382                         terrainlight = terrain.getLighting(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z);
383                         Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, terrainlight.x * 190 / 255, terrainlight.y * 170 / 255, terrainlight.z * 108 / 255, .5, .7);
384                     }
385
386                     else if (environment == grassyenvironment && findLengthfast(&bounceness) > 500 && terrain.getOpacity(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z) < .2) {
387                         terrainlight = terrain.getLighting(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z);
388                         Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, terrainlight.x * 90 / 255, terrainlight.y * 70 / 255, terrainlight.z * 8 / 255, .5, .5);
389                     } else if (findLengthfast(&bounceness) > 500)
390                         Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, terrainlight.x, terrainlight.y, terrainlight.z, .5, .2);
391
392
393                     joints[i].position.y = (terrain.getHeight(joints[i].position.x * (*scale) + coords->x, joints[i].position.z * (*scale) + coords->z) + groundlevel - coords->y) / (*scale);
394                     if (longdead > 100)
395                         broken = 1;
396                 }
397                 if (terrain.patchobjectnum[whichpatchx][whichpatchz])
398                     for (m = 0; m < terrain.patchobjectnum[whichpatchx][whichpatchz]; m++) {
399                         k = terrain.patchobjects[whichpatchx][whichpatchz][m];
400                         if (k < objects.numobjects && k >= 0)
401                             if (objects.possible[k]) {
402                                 friction = objects.friction[k];
403                                 start = joints[i].realoldposition;
404                                 end = joints[i].position * (*scale) + *coords;
405                                 whichhit = objects.model[k].LineCheckPossible(&start, &end, &temp, &objects.position[k], &objects.yaw[k]);
406                                 if (whichhit != -1) {
407                                     if (joints[i].label == groin && !joints[i].locked && joints[i].delay <= 0) {
408                                         joints[i].locked = 1;
409                                         joints[i].delay = 1;
410                                         if (tutoriallevel != 1 || id == 0) {
411                                             emit_sound_at(landsound1, joints[i].position * (*scale) + *coords, 128.);
412                                         }
413                                         breaking = 1;
414                                     }
415
416                                     if (joints[i].label == head && !joints[i].locked && joints[i].delay <= 0) {
417                                         joints[i].locked = 1;
418                                         joints[i].delay = 1;
419                                         if (tutoriallevel != 1 || id == 0) {
420                                             emit_sound_at(landsound2, joints[i].position * (*scale) + *coords, 128.);
421                                         }
422                                     }
423
424                                     terrainnormal = DoRotation(objects.model[k].facenormals[whichhit], 0, objects.yaw[k], 0) * -1;
425                                     if (terrainnormal.y > .8)
426                                         freefall = 0;
427                                     bounceness = terrainnormal * findLength(&joints[i].velocity) * (abs(normaldotproduct(joints[i].velocity, terrainnormal)));
428                                     if (findLengthfast(&joints[i].velocity) > findLengthfast(&joints[i].oldvelocity)) {
429                                         bounceness = 0;
430                                         joints[i].velocity = joints[i].oldvelocity;
431                                     }
432                                     if (tutoriallevel != 1 || id == 0)
433                                         if (findLengthfast(&bounceness) > 4000 && breaking) {
434                                             objects.model[k].MakeDecal(breakdecal, DoRotation(temp - objects.position[k], 0, -objects.yaw[k], 0), .4, .5, Random() % 360);
435                                             Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, 1, 1, 1, 4, .2);
436                                             breaking = 0;
437                                             camerashake += .6;
438
439                                             emit_sound_at(breaksound2, joints[i].position * (*scale) + *coords);
440
441                                             envsound[numenvsounds] = *coords;
442                                             envsoundvol[numenvsounds] = 64;
443                                             envsoundlife[numenvsounds] = .4;
444                                             numenvsounds++;
445                                         }
446                                     if (objects.type[k] == treetrunktype) {
447                                         //if(objects.rotx[k]==0||objects.roty[k]==0){
448                                         /*int howmany;
449                                         XYZ tempvel;
450                                         XYZ pos;
451                                         if(environment==grassyenvironment)howmany=findLength(&joints[i].velocity)*4/10;
452                                         if(environment==snowyenvironment)howmany=findLength(&joints[i].velocity)*1/10;
453                                         if(environment!=desertenvironment)
454                                         for(j=0;j<howmany;j++){
455                                         tempvel.x=float(abs(Random()%100)-50)/20;
456                                         tempvel.y=float(abs(Random()%100)-50)/20;
457                                         tempvel.z=float(abs(Random()%100)-50)/20;
458                                         pos=objects.position[k];
459                                         pos.y+=objects.scale[k]*15;
460                                         pos.x+=float(abs(Random()%100)-50)/100*objects.scale[k]*5;
461                                         pos.y+=float(abs(Random()%100)-50)/100*objects.scale[k]*15;
462                                         pos.z+=float(abs(Random()%100)-50)/100*objects.scale[k]*5;
463                                         Sprite::MakeSprite(splintersprite, pos,tempvel*.5, 165/255+float(abs(Random()%100)-50)/400,0,0, .2+float(abs(Random()%100)-50)/1300, 1);
464                                         Sprite::special[Sprite::numsprites-1]=1;
465                                         }*/
466                                         objects.rotx[k] += joints[i].velocity.x * multiplier * .4;
467                                         objects.roty[k] += joints[i].velocity.z * multiplier * .4;
468                                         objects.rotx[k + 1] += joints[i].velocity.x * multiplier * .4;
469                                         objects.roty[k + 1] += joints[i].velocity.z * multiplier * .4;
470                                     }
471                                     if (!joints[i].locked)
472                                         damage += findLengthfast(&bounceness) / 2500;
473                                     ReflectVector(&joints[i].velocity, &terrainnormal);
474                                     frictionness = abs(normaldotproduct(joints[i].velocity, terrainnormal)); //findLength(&bounceness)/findLength(&joints[i].velocity);
475                                     joints[i].velocity -= bounceness;
476                                     if (1 - friction * frictionness > 0)
477                                         joints[i].velocity *= 1 - friction * frictionness;
478                                     else
479                                         joints[i].velocity = 0;
480                                     if (findLengthfast(&bounceness) > 2500) {
481                                         Normalise(&bounceness);
482                                         bounceness = bounceness * 50;
483                                     }
484                                     joints[i].velocity += bounceness * elasticity;
485
486
487                                     if (!joints[i].locked)
488                                         if (findLengthfast(&joints[i].velocity) < 1) {
489                                             joints[i].locked = 1;
490                                             //joints[i].velocity*=3;
491                                         }
492                                     if (findLengthfast(&bounceness) > 500)
493                                         Sprite::MakeSprite(cloudsprite, joints[i].position * (*scale) + *coords, joints[i].velocity * .06, 1, 1, 1, .5, .2);
494                                     joints[i].position = (temp - *coords) / (*scale) + terrainnormal * .005;
495                                     if (longdead > 100)
496                                         broken = 1;
497                                 }
498                             }
499                     }
500                 joints[i].realoldposition = joints[i].position * (*scale) + *coords;
501             }
502         }
503         multiplier = tempmult;
504
505
506         if (terrain.patchobjectnum[whichpatchx][whichpatchz])
507             for (m = 0; m < terrain.patchobjectnum[whichpatchx][whichpatchz]; m++) {
508                 k = terrain.patchobjects[whichpatchx][whichpatchz][m];
509                 if (objects.possible[k]) {
510                     for (i = 0; i < 26; i++) {
511                         //Make this less stupid
512                         start = joints[jointlabels[whichjointstartarray[i]]].position * (*scale) + *coords;
513                         end = joints[jointlabels[whichjointendarray[i]]].position * (*scale) + *coords;
514                         whichhit = objects.model[k].LineCheckSlidePossible(&start, &end, &temp, &objects.position[k], &objects.yaw[k]);
515                         if (whichhit != -1) {
516                             joints[jointlabels[whichjointendarray[i]]].position = (end - *coords) / (*scale);
517                             for (j = 0; j < num_muscles; j++) {
518                                 if ((muscles[j].parent1->label == whichjointstartarray[i] && muscles[j].parent2->label == whichjointendarray[i]) || (muscles[j].parent2->label == whichjointstartarray[i] && muscles[j].parent1->label == whichjointendarray[i]))
519                                     muscles[j].DoConstraint(spinny);
520                             }
521                         }
522                     }
523                 }
524             }
525
526         for (i = 0; i < num_joints; i++) {
527             groundlevel = .15;
528             if (joints[i].label == head)
529                 groundlevel = .8;
530             if (joints[i].label == righthand || joints[i].label == rightwrist || joints[i].label == rightelbow)
531                 groundlevel = .2;
532             if (joints[i].label == lefthand || joints[i].label == leftwrist || joints[i].label == leftelbow)
533                 groundlevel = .2;
534             joints[i].position.y += groundlevel;
535             joints[i].mass = 1;
536             if (joints[i].label == lefthip || joints[i].label == leftknee || joints[i].label == leftankle || joints[i].label == righthip || joints[i].label == rightknee || joints[i].label == rightankle)
537                 joints[i].mass = 2;
538             if (joints[i].locked) {
539                 joints[i].mass = 4;
540             }
541         }
542
543         return damage;
544     }
545     if (!free) {
546         for (i = 0; i < num_muscles; i++) {
547             if (muscles[i].type == boneconnect)
548                 muscles[i].DoConstraint(0);
549         }
550     }
551     return 0;
552 }
553
554 void Skeleton::DoGravity(float *scale)
555 {
556     static int i;
557     for (i = 0; i < num_joints; i++) {
558         if (((joints[i].label != leftknee && joints[i].label != rightknee) || lowforward.y > -.1 || joints[i].mass < 5) && ((joints[i].label != rightelbow && joints[i].label != rightelbow) || forward.y < .3))
559             joints[i].velocity.y += gravity * multiplier / (*scale);
560     }
561 }
562
563 void Skeleton::Draw(int  muscleview)
564 {
565     static float jointcolor[4];
566
567     if (muscleview != 2) {
568         jointcolor[0] = 0;
569         jointcolor[1] = 0;
570         jointcolor[2] = .5;
571         jointcolor[3] = 1;
572     }
573
574     if (muscleview == 2) {
575         jointcolor[0] = 0;
576         jointcolor[1] = 0;
577         jointcolor[2] = 0;
578         jointcolor[3] = .5;
579     }
580     //Calc motionblur-ness
581     for (int i = 0; i < num_joints; i++) {
582         joints[i].oldposition = joints[i].position;
583         joints[i].blurred = findDistance(&joints[i].position, &joints[i].oldposition) * 100;
584         if (joints[i].blurred < 1)
585             joints[i].blurred = 1;
586     }
587
588     //Do Motionblur
589     glDepthMask(0);
590     glEnable(GL_BLEND);
591     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
592     glBegin(GL_QUADS);
593     for (int i = 0; i < num_joints; i++) {
594         if (joints[i].hasparent) {
595             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / joints[i].blurred);
596             glVertex3f(joints[i].position.x, joints[i].position.y, joints[i].position.z);
597             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / joints[i].parent->blurred);
598             glVertex3f(joints[i].parent->position.x, joints[i].parent->position.y, joints[i].parent->position.z);
599             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / joints[i].parent->blurred);
600             glVertex3f(joints[i].parent->oldposition.x, joints[i].parent->oldposition.y, joints[i].parent->oldposition.z);
601             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / joints[i].blurred);
602             glVertex3f(joints[i].oldposition.x, joints[i].oldposition.y, joints[i].oldposition.z);
603         }
604     }
605     for (int i = 0; i < num_muscles; i++) {
606         if (muscles[i].type == boneconnect) {
607             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / muscles[i].parent2->blurred);
608             glVertex3f(muscles[i].parent1->position.x, muscles[i].parent1->position.y, muscles[i].parent1->position.z);
609             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / muscles[i].parent2->blurred);
610             glVertex3f(muscles[i].parent2->position.x, muscles[i].parent2->position.y, muscles[i].parent2->position.z);
611             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / muscles[i].parent2->blurred);
612             glVertex3f(muscles[i].parent2->oldposition.x, muscles[i].parent2->oldposition.y, muscles[i].parent2->oldposition.z);
613             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / muscles[i].parent1->blurred);
614             glVertex3f(muscles[i].parent1->oldposition.x, muscles[i].parent1->oldposition.y, muscles[i].parent1->oldposition.z);
615         }
616     }
617     glEnd();
618
619     glBegin(GL_LINES);
620     for (int i = 0; i < num_joints; i++) {
621         if (joints[i].hasparent) {
622             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / joints[i].blurred);
623             glVertex3f(joints[i].position.x, joints[i].position.y, joints[i].position.z);
624             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / joints[i].parent->blurred);
625             glVertex3f(joints[i].parent->position.x, joints[i].parent->position.y, joints[i].parent->position.z);
626         }
627     }
628     /*for(int i=0; i<num_joints; i++){
629     if(joints[i].hasparent){
630     glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],1);
631     glVertex3f(joints[i].position.x,joints[i].position.y,joints[i].position.z);
632     glColor4f(jointcolor[0],jointcolor[1],jointcolor[2],1);
633     glVertex3f(joints[i].position.x+forward.x,joints[i].position.y+forward.y,joints[i].position.z+forward.z);
634     }
635     }*/
636     for (int i = 0; i < num_muscles; i++) {
637         if (muscles[i].type == boneconnect) {
638             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / muscles[i].parent1->blurred);
639             glVertex3f(muscles[i].parent1->position.x, muscles[i].parent1->position.y, muscles[i].parent1->position.z);
640             glColor4f(jointcolor[0], jointcolor[1], jointcolor[2], jointcolor[3] / muscles[i].parent2->blurred);
641             glVertex3f(muscles[i].parent2->position.x, muscles[i].parent2->position.y, muscles[i].parent2->position.z);
642         }
643     }
644     glColor3f(.6, .6, 0);
645     if (muscleview == 1)
646         for (int i = 0; i < num_muscles; i++) {
647             if (muscles[i].type != boneconnect) {
648                 glVertex3f(muscles[i].parent1->position.x, muscles[i].parent1->position.y, muscles[i].parent1->position.z);
649                 glVertex3f(muscles[i].parent2->position.x, muscles[i].parent2->position.y, muscles[i].parent2->position.z);
650             }
651         }
652     glEnd();
653
654     if (muscleview != 2) {
655         glPointSize(3);
656         glBegin(GL_POINTS);
657         for (int i = 0; i < num_joints; i++) {
658             if (i != selected)
659                 glColor4f(0, 0, .5, 1);
660             if (i == selected)
661                 glColor4f(1, 1, 0, 1);
662             if (joints[i].locked && i != selected)
663                 glColor4f(1, 0, 0, 1);
664             glVertex3f(joints[i].position.x, joints[i].position.y, joints[i].position.z);
665         }
666         glEnd();
667     }
668
669     //Set old position to current position
670     if (muscleview == 2)
671         for (int i = 0; i < num_joints; i++) {
672             joints[i].oldposition = joints[i].position;
673         }
674     glDepthMask(1);
675 }
676
677 void Skeleton::AddJoint(float x, float y, float z, int which)
678 {
679     if (num_joints < max_joints - 1) {
680         joints[num_joints].velocity = 0;
681         joints[num_joints].position.x = x;
682         joints[num_joints].position.y = y;
683         joints[num_joints].position.z = z;
684         joints[num_joints].mass = 1;
685         joints[num_joints].locked = 0;
686
687         /*if(which>=num_joints||which<0)*/
688         joints[num_joints].hasparent = 0;
689         /*if(which<num_joints&&which>=0){
690         joints[num_joints].parent=&joints[which];
691         joints[num_joints].hasparent=1;
692         joints[num_joints].length=findDistance(joints[num_joints].position,joints[num_joints].parent->position);
693         }*/
694         num_joints++;
695         if (which < num_joints && which >= 0)
696             AddMuscle(num_joints - 1, which, 0, 10, boneconnect);
697     }
698 }
699
700 void Skeleton::DeleteJoint(int whichjoint)
701 {
702     if (whichjoint < num_joints && whichjoint >= 0) {
703         joints[whichjoint].velocity = joints[num_joints - 1].velocity;
704         joints[whichjoint].position = joints[num_joints - 1].position;
705         joints[whichjoint].oldposition = joints[num_joints - 1].oldposition;
706         joints[whichjoint].hasparent = joints[num_joints - 1].hasparent;
707         joints[whichjoint].parent = joints[num_joints - 1].parent;
708         joints[whichjoint].length = joints[num_joints - 1].length;
709         joints[whichjoint].locked = joints[num_joints - 1].locked;
710         joints[whichjoint].modelnum = joints[num_joints - 1].modelnum;
711         joints[whichjoint].visible = joints[num_joints - 1].visible;
712
713         for (int i = 0; i < num_muscles; i++) {
714             while (muscles[i].parent1 == &joints[whichjoint] && i < num_muscles)DeleteMuscle(i);
715             while (muscles[i].parent2 == &joints[whichjoint] && i < num_muscles)DeleteMuscle(i);
716         }
717         for (int i = 0; i < num_muscles; i++) {
718             while (muscles[i].parent1 == &joints[num_joints - 1] && i < num_muscles)muscles[i].parent1 = &joints[whichjoint];
719             while (muscles[i].parent2 == &joints[num_joints - 1] && i < num_muscles)muscles[i].parent2 = &joints[whichjoint];
720         }
721         for (int i = 0; i < num_joints; i++) {
722             if (joints[i].parent == &joints[whichjoint])
723                 joints[i].hasparent = 0;
724         }
725         for (int i = 0; i < num_joints; i++) {
726             if (joints[i].parent == &joints[num_joints - 1])
727                 joints[i].parent = &joints[whichjoint];
728         }
729
730         num_joints--;
731     }
732 }
733
734 void Skeleton::DeleteMuscle(int whichmuscle)
735 {
736     if (whichmuscle < num_muscles) {
737         muscles[whichmuscle].minlength = muscles[num_muscles - 1].minlength;
738         muscles[whichmuscle].maxlength = muscles[num_muscles - 1].maxlength;
739         muscles[whichmuscle].strength = muscles[num_muscles - 1].strength;
740         muscles[whichmuscle].parent1 = muscles[num_muscles - 1].parent1;
741         muscles[whichmuscle].parent2 = muscles[num_muscles - 1].parent2;
742         muscles[whichmuscle].length = muscles[num_muscles - 1].length;
743         muscles[whichmuscle].visible = muscles[num_muscles - 1].visible;
744         muscles[whichmuscle].type = muscles[num_muscles - 1].type;
745         muscles[whichmuscle].targetlength = muscles[num_muscles - 1].targetlength;
746
747         num_muscles--;
748     }
749 }
750
751 void Skeleton::SetJoint(float x, float y, float z, int which, int whichjoint)
752 {
753     if (whichjoint < num_joints) {
754         joints[whichjoint].velocity = 0;
755         joints[whichjoint].position.x = x;
756         joints[whichjoint].position.y = y;
757         joints[whichjoint].position.z = z;
758
759         if (which >= num_joints || which < 0)
760             joints[whichjoint].hasparent = 0;
761         if (which < num_joints && which >= 0) {
762             joints[whichjoint].parent = &joints[which];
763             joints[whichjoint].hasparent = 1;
764             joints[whichjoint].length = findDistance(&joints[whichjoint].position, &joints[whichjoint].parent->position);
765         }
766     }
767 }
768
769 void Skeleton::AddMuscle(int attach1, int attach2, float minlength, float maxlength, int type)
770 {
771     const int max_muscles = 100; // FIXME: Probably can be dropped
772     if (num_muscles < max_muscles - 1 && attach1 < num_joints && attach1 >= 0 && attach2 < num_joints && attach2 >= 0 && attach1 != attach2) {
773         muscles[num_muscles].parent1 = &joints[attach1];
774         muscles[num_muscles].parent2 = &joints[attach2];
775         muscles[num_muscles].length = findDistance(&muscles[num_muscles].parent1->position, &muscles[num_muscles].parent2->position);
776         muscles[num_muscles].targetlength = findDistance(&muscles[num_muscles].parent1->position, &muscles[num_muscles].parent2->position);
777         muscles[num_muscles].strength = .7;
778         muscles[num_muscles].type = type;
779         muscles[num_muscles].minlength = minlength;
780         muscles[num_muscles].maxlength = maxlength;
781
782         num_muscles++;
783     }
784 }
785
786 void Skeleton::MusclesSet()
787 {
788     for (int i = 0; i < num_muscles; i++) {
789         muscles[i].length = findDistance(&muscles[i].parent1->position, &muscles[i].parent2->position);
790     }
791 }
792
793 void Skeleton::DoBalance()
794 {
795     /*XYZ newpoint;
796     newpoint=joints[0].position;
797     newpoint.x=(joints[2].position.x+joints[4].position.x)/2;
798     newpoint.z=(joints[2].position.z+joints[4].position.z)/2;
799     joints[0].velocity=joints[0].velocity+(newpoint-joints[0].position);
800     //Move child point to within certain distance of parent point
801     joints[0].position=newpoint;
802
803     MusclesSet();*/
804 }
805
806 void Skeleton::FindRotationMuscle(int which, int animation)
807 {
808     static XYZ temppoint1, temppoint2, tempforward;
809     static float distance;
810
811     temppoint1 = muscles[which].parent1->position;
812     temppoint2 = muscles[which].parent2->position;
813     distance = sqrt((temppoint1.x - temppoint2.x) * (temppoint1.x - temppoint2.x) + (temppoint1.y - temppoint2.y) * (temppoint1.y - temppoint2.y) + (temppoint1.z - temppoint2.z) * (temppoint1.z - temppoint2.z));
814     if ((temppoint1.y - temppoint2.y) <= distance)
815         muscles[which].rotate2 = asin((temppoint1.y - temppoint2.y) / distance);
816     if ((temppoint1.y - temppoint2.y) > distance)
817         muscles[which].rotate2 = asin(1.f);
818     muscles[which].rotate2 *= 360 / 6.28;
819     temppoint1.y = 0;
820     temppoint2.y = 0;
821     distance = sqrt((temppoint1.x - temppoint2.x) * (temppoint1.x - temppoint2.x) + (temppoint1.y - temppoint2.y) * (temppoint1.y - temppoint2.y) + (temppoint1.z - temppoint2.z) * (temppoint1.z - temppoint2.z));
822     if ((temppoint1.z - temppoint2.z) <= distance)
823         muscles[which].rotate1 = acos((temppoint1.z - temppoint2.z) / distance);
824     if ((temppoint1.z - temppoint2.z) > distance)
825         muscles[which].rotate1 = acos(1.f);
826     muscles[which].rotate1 *= 360 / 6.28;
827     if (temppoint1.x > temppoint2.x)
828         muscles[which].rotate1 = 360 - muscles[which].rotate1;
829     if (!isnormal(muscles[which].rotate1))
830         muscles[which].rotate1 = 0;
831     if (!isnormal(muscles[which].rotate2))
832         muscles[which].rotate2 = 0;
833
834     if (muscles[which].parent1->label == head)
835         tempforward = specialforward[0];
836     else if (muscles[which].parent1->label == rightshoulder || muscles[which].parent1->label == rightelbow || muscles[which].parent1->label == rightwrist || muscles[which].parent1->label == righthand)
837         tempforward = specialforward[1];
838     else if (muscles[which].parent1->label == leftshoulder || muscles[which].parent1->label == leftelbow || muscles[which].parent1->label == leftwrist || muscles[which].parent1->label == lefthand)
839         tempforward = specialforward[2];
840     else if (muscles[which].parent1->label == righthip || muscles[which].parent1->label == rightknee || muscles[which].parent1->label == rightankle || muscles[which].parent1->label == rightfoot)
841         tempforward = specialforward[3];
842     else if (muscles[which].parent1->label == lefthip || muscles[which].parent1->label == leftknee || muscles[which].parent1->label == leftankle || muscles[which].parent1->label == leftfoot)
843         tempforward = specialforward[4];
844     else if (!muscles[which].parent1->lower)
845         tempforward = forward;
846     else if (muscles[which].parent1->lower)
847         tempforward = lowforward;
848
849     if (animation == hanganim) {
850         if (muscles[which].parent1->label == righthand || muscles[which].parent2->label == righthand) {
851             tempforward = 0;
852             tempforward.x = -1;
853         }
854         if (muscles[which].parent1->label == lefthand || muscles[which].parent2->label == lefthand) {
855             tempforward = 0;
856             tempforward.x = 1;
857         }
858     }
859
860     if (free == 0) {
861         if (muscles[which].parent1->label == rightfoot || muscles[which].parent2->label == rightfoot) {
862             tempforward.y -= .3;
863         }
864         if (muscles[which].parent1->label == leftfoot || muscles[which].parent2->label == leftfoot) {
865             tempforward.y -= .3;
866         }
867     }
868
869
870     tempforward = DoRotation(tempforward, 0, muscles[which].rotate1 - 90, 0);
871     tempforward = DoRotation(tempforward, 0, 0, muscles[which].rotate2 - 90);
872     tempforward.y = 0;
873     tempforward /= sqrt(tempforward.x * tempforward.x + tempforward.y * tempforward.y + tempforward.z * tempforward.z);
874     if (tempforward.z <= 1 && tempforward.z >= -1)
875         muscles[which].rotate3 = acos(0 - tempforward.z);
876     else
877         muscles[which].rotate3 = acos(-1.f);
878     muscles[which].rotate3 *= 360 / 6.28;
879     if (0 > tempforward.x)
880         muscles[which].rotate3 = 360 - muscles[which].rotate3;
881     if (!isnormal(muscles[which].rotate3))
882         muscles[which].rotate3 = 0;
883 }
884
885 void Animation::Load(const char *filename, int aheight, int aattack)
886 {
887     static FILE *tfile;
888     static int i, j;
889     static XYZ startoffset, endoffset;
890     static int howmany;
891
892     static const char *anim_prefix = ":Data:Animations:";
893
894
895     LOGFUNC;
896
897     int len = strlen(anim_prefix) + strlen(filename);
898     char *buf = new char[len + 1];
899     snprintf(buf, len + 1, "%s%s", anim_prefix, filename);
900     // Changing the filename into something the OS can understand
901     char *fixedFN = ConvertFileName(buf);
902     delete[] buf;
903
904     LOG(std::string("Loading animation...") + fixedFN);
905
906     deallocate();
907
908     height = aheight;
909     attack = aattack;
910
911     if (visibleloading)
912         Game::LoadingScreen();
913
914     tfile = fopen( fixedFN, "rb" );
915     if (tfile) {
916         funpackf(tfile, "Bi Bi", &numframes, &joints);
917         /*
918         for(i = 0; i < joints; i++){
919         if(position[i])dealloc2(position[i]);
920         if(twist[i])dealloc2(twist[i]);
921         if(twist2[i])dealloc2(twist2[i]);
922         if(onground[i])dealloc2(onground[i]);
923         }*/
924         /*
925         if(position)dealloc2(position);
926         if(twist)dealloc2(twist);
927         if(twist2)dealloc2(twist2);
928         if(speed)dealloc2(speed);
929         if(onground)dealloc2(onground);
930         if(forward)dealloc2(forward);
931         if(weapontarget)dealloc2(weapontarget);
932         if(label)dealloc2(label);*/
933
934         position = (XYZ**)malloc(sizeof(XYZ*)*joints);
935         for (i = 0; i < joints; i++)
936             position[i] = (XYZ*)malloc(sizeof(XYZ) * numframes);
937
938         twist = (float**)malloc(sizeof(float*)*joints);
939         for (i = 0; i < joints; i++)
940             twist[i] = (float*)malloc(sizeof(float) * numframes);
941
942         twist2 = (float**)malloc(sizeof(float*)*joints);
943         for (i = 0; i < joints; i++)
944             twist2[i] = (float*)malloc(sizeof(float) * numframes);
945
946         speed = (float*)malloc(sizeof(float) * numframes);
947
948         onground = (bool**)malloc(sizeof(bool*)*joints);
949         for (i = 0; i < joints; i++)
950             onground[i] = (bool*)malloc(sizeof(bool) * numframes);
951
952         forward = (XYZ*)malloc(sizeof(XYZ) * numframes);
953         weapontarget = (XYZ*)malloc(sizeof(XYZ) * numframes);
954         label = (int*)malloc(sizeof(int) * numframes);
955
956         /*position = new XYZ[joints][numframes];
957         twist = new float[joints][numframes];
958         twist2 = new float[joints][numframes];
959         speed = new float[numframes];
960         onground = new bool[joints][numframes];
961         forward = new XYZ[numframes];
962         label = new int[numframes];*/
963
964         for (i = 0; i < numframes; i++) {
965             for (j = 0; j < joints; j++) {
966                 funpackf(tfile, "Bf Bf Bf", &position[j][i].x, &position[j][i].y, &position[j][i].z);
967             }
968             for (j = 0; j < joints; j++) {
969                 funpackf(tfile, "Bf", &twist[j][i]);
970             }
971             for (j = 0; j < joints; j++) {
972                 unsigned char uch;
973                 funpackf(tfile, "Bb", &uch);
974                 onground[j][i] = (uch != 0);
975             }
976             funpackf(tfile, "Bf", &speed[i]);
977         }
978         for (i = 0; i < numframes; i++) {
979             for (j = 0; j < joints; j++) {
980                 funpackf(tfile, "Bf", &twist2[j][i]);
981             }
982         }
983         for (i = 0; i < numframes; i++) {
984             funpackf(tfile, "Bf", &label[i]);
985         }
986         funpackf(tfile, "Bi", &weapontargetnum);
987         for (i = 0; i < numframes; i++) {
988             funpackf(tfile, "Bf Bf Bf", &weapontarget[i].x, &weapontarget[i].y, &weapontarget[i].z);
989         }
990
991         fclose(tfile);
992     }
993
994     startoffset = 0;
995     endoffset = 0;
996     howmany = 0;
997     for (j = 0; j < joints; j++) {
998         if (position[j][0].y < 1)
999             startoffset += position[j][0];
1000         if (position[j][numframes - 1].y < 1)
1001             endoffset += position[j][numframes - 1];
1002         howmany++;
1003     }
1004     startoffset /= howmany;
1005     endoffset /= howmany;
1006     offset = endoffset;
1007     offset.y = 0;
1008 }
1009
1010
1011 void Animation::Move(XYZ how)
1012 {
1013     static int i, j, joints;
1014     for (i = 0; i < numframes; i++) {
1015         for (j = 0; j < joints; j++) {
1016             position[j][i] = 0;
1017         }
1018     }
1019 }
1020
1021 void Skeleton::Load(const char *filename,       const char *lowfilename, const char *clothesfilename,
1022                     const char *modelfilename,  const char *model2filename,
1023                     const char *model3filename, const char *model4filename,
1024                     const char *model5filename, const char *model6filename,
1025                     const char *model7filename, const char *modellowfilename,
1026                     const char *modelclothesfilename, bool aclothes)
1027 {
1028     static GLfloat M[16];
1029     static int parentID;
1030     static FILE *tfile;
1031     static float lSize;
1032     static int i, j, tempmuscle;
1033     int newload;
1034     int edit;
1035
1036     LOGFUNC;
1037
1038
1039     newload = 0;
1040
1041     num_models = 7;
1042
1043     clothes = aclothes;
1044
1045     for (i = 0; i < num_models; i++) {
1046         if (i == 0) model[i].loadnotex(modelfilename);
1047         if (i == 1) model[i].loadnotex(model2filename);
1048         if (i == 2) model[i].loadnotex(model3filename);
1049         if (i == 3) model[i].loadnotex(model4filename);
1050         if (i == 4) model[i].loadnotex(model5filename);
1051         if (i == 5) model[i].loadnotex(model6filename);
1052         if (i == 6) model[i].loadnotex(model7filename);
1053         model[i].Rotate(180, 0, 0);
1054         model[i].Scale(.04, .04, .04);
1055         model[i].CalculateNormals(0);
1056     }
1057
1058     drawmodel.load(modelfilename, 0);
1059     drawmodel.Rotate(180, 0, 0);
1060     drawmodel.Scale(.04, .04, .04);
1061     drawmodel.FlipTexCoords();
1062     if (tutoriallevel == 1 && id != 0)
1063         drawmodel.UniformTexCoords();
1064     if (tutoriallevel == 1 && id != 0)
1065         drawmodel.ScaleTexCoords(0.1);
1066     drawmodel.CalculateNormals(0);
1067
1068     modellow.loadnotex(modellowfilename);
1069     modellow.Rotate(180, 0, 0);
1070     modellow.Scale(.04, .04, .04);
1071     modellow.CalculateNormals(0);
1072
1073     drawmodellow.load(modellowfilename, 0);
1074     drawmodellow.Rotate(180, 0, 0);
1075     drawmodellow.Scale(.04, .04, .04);
1076     drawmodellow.FlipTexCoords();
1077     if (tutoriallevel == 1 && id != 0)
1078         drawmodellow.UniformTexCoords();
1079     if (tutoriallevel == 1 && id != 0)
1080         drawmodellow.ScaleTexCoords(0.1);
1081     drawmodellow.CalculateNormals(0);
1082
1083     if (clothes) {
1084         modelclothes.loadnotex(modelclothesfilename);
1085         modelclothes.Rotate(180, 0, 0);
1086         modelclothes.Scale(.041, .04, .041);
1087         modelclothes.CalculateNormals(0);
1088
1089         drawmodelclothes.load(modelclothesfilename, 0);
1090         drawmodelclothes.Rotate(180, 0, 0);
1091         drawmodelclothes.Scale(.04, .04, .04);
1092         drawmodelclothes.FlipTexCoords();
1093         drawmodelclothes.CalculateNormals(0);
1094     }
1095
1096     tfile = fopen( ConvertFileName(filename), "rb" );
1097     if (1) {
1098         funpackf(tfile, "Bi", &num_joints);
1099         //joints.resize(num_joints);
1100         if (joints)
1101             delete [] joints; //dealloc2(joints);
1102         joints = (Joint*)new Joint[num_joints]; //malloc(sizeof(Joint)*num_joints);
1103
1104         for (i = 0; i < num_joints; i++) {
1105             funpackf(tfile, "Bf Bf Bf Bf Bf", &joints[i].position.x, &joints[i].position.y, &joints[i].position.z, &joints[i].length, &joints[i].mass);
1106             funpackf(tfile, "Bb Bb", &joints[i].hasparent, &joints[i].locked);
1107             funpackf(tfile, "Bi", &joints[i].modelnum);
1108             funpackf(tfile, "Bb Bb", &joints[i].visible, &joints[i].sametwist);
1109             funpackf(tfile, "Bi Bi", &joints[i].label, &joints[i].hasgun);
1110             funpackf(tfile, "Bb", &joints[i].lower);
1111             funpackf(tfile, "Bi", &parentID);
1112             if (joints[i].hasparent)
1113                 joints[i].parent = &joints[parentID];
1114             joints[i].velocity = 0;
1115             joints[i].oldposition = joints[i].position;
1116         }
1117         tempmuscle = num_muscles;
1118         funpackf(tfile, "Bi", &num_muscles);
1119         //muscles.clear();
1120         if (muscles)
1121             delete [] muscles; //dealloc2(muscles);
1122         muscles = (Muscle*)new Muscle[num_muscles]; //malloc(sizeof(Muscle)*num_muscles);
1123         newload = 1;
1124         for (i = 0; i < num_muscles; i++) {
1125             tempmuscle = muscles[i].numvertices;
1126             funpackf(tfile, "Bf Bf Bf Bf Bf Bi Bi", &muscles[i].length, &muscles[i].targetlength, &muscles[i].minlength, &muscles[i].maxlength, &muscles[i].strength, &muscles[i].type, &muscles[i].numvertices);
1127             //muscles[i].vertices.clear();
1128             //muscles[i].vertices.resize(muscles[i].numvertices);
1129             //if(muscles[i].vertices)dealloc2(muscles[i].vertices);
1130             muscles[i].vertices = (int*)malloc(sizeof(int) * muscles[i].numvertices);
1131
1132             edit = 0;
1133             for (j = 0; j < muscles[i].numvertices - edit; j++) {
1134                 funpackf(tfile, "Bi", &muscles[i].vertices[j + edit]);
1135                 if (muscles[i].vertices[j + edit] >= model[0].vertexNum) {
1136                     muscles[i].numvertices--;
1137                     edit--;
1138                 }
1139             }
1140             funpackf(tfile, "Bb Bi", &muscles[i].visible, &parentID);
1141             muscles[i].parent1 = &joints[parentID];
1142             funpackf(tfile, "Bi", &parentID);
1143             muscles[i].parent2 = &joints[parentID];
1144         }
1145         for (j = 0; j < 3; j++) {
1146             funpackf(tfile, "Bi", &forwardjoints[j]);
1147         }
1148         for (j = 0; j < 3; j++) {
1149             funpackf(tfile, "Bi", &lowforwardjoints[j]);
1150         }
1151         for (j = 0; j < num_muscles; j++) {
1152             for (i = 0; i < muscles[j].numvertices; i++) {
1153                 for (int k = 0; k < num_models; k++) {
1154                     if (muscles[j].numvertices && muscles[j].vertices[i] < model[k].vertexNum)
1155                         model[k].owner[muscles[j].vertices[i]] = j;
1156                 }
1157             }
1158         }
1159         FindForwards();
1160         for (i = 0; i < num_joints; i++) {
1161             joints[i].startpos = joints[i].position;
1162         }
1163         for (i = 0; i < num_muscles; i++) {
1164             FindRotationMuscle(i, -1);
1165         }
1166         for (int k = 0; k < num_models; k++) {
1167             for (i = 0; i < model[k].vertexNum; i++) {
1168                 model[k].vertex[i] = model[k].vertex[i] - (muscles[model[k].owner[i]].parent1->position + muscles[model[k].owner[i]].parent2->position) / 2;
1169                 glMatrixMode(GL_MODELVIEW);                                                     // Select The Modelview Matrix
1170                 glPushMatrix();
1171                 glLoadIdentity();
1172                 glRotatef(muscles[model[k].owner[i]].rotate3, 0, 1, 0);
1173                 glRotatef(muscles[model[k].owner[i]].rotate2 - 90, 0, 0, 1);
1174                 glRotatef(muscles[model[k].owner[i]].rotate1 - 90, 0, 1, 0);
1175                 glTranslatef(model[k].vertex[i].x, model[k].vertex[i].y, model[k].vertex[i].z);
1176                 glGetFloatv(GL_MODELVIEW_MATRIX, M);
1177                 model[k].vertex[i].x = M[12] * 1;
1178                 model[k].vertex[i].y = M[13] * 1;
1179                 model[k].vertex[i].z = M[14] * 1;
1180                 glPopMatrix();
1181             }
1182             model[k].CalculateNormals(0);
1183         }
1184     }
1185     fclose(tfile);
1186
1187     tfile = fopen( ConvertFileName(lowfilename), "rb" );
1188     if (1) {
1189         lSize = sizeof(num_joints);
1190         fseek ( tfile, lSize, SEEK_CUR);
1191         //joints = new Joint[num_joints];
1192         //jointlabels = new int[num_joints];
1193         for (i = 0; i < num_joints; i++) {
1194             lSize = sizeof(XYZ);
1195             fseek ( tfile, lSize, SEEK_CUR);
1196             lSize = sizeof(float);
1197             fseek ( tfile, lSize, SEEK_CUR);
1198             lSize = sizeof(float);
1199             fseek ( tfile, lSize, SEEK_CUR);
1200             lSize = 1; //sizeof(bool);
1201             fseek ( tfile, lSize, SEEK_CUR);
1202             lSize = 1; //sizeof(bool);
1203             fseek ( tfile, lSize, SEEK_CUR);
1204             lSize = sizeof(int);
1205             fseek ( tfile, lSize, SEEK_CUR);
1206             lSize = 1; //sizeof(bool);
1207             fseek ( tfile, lSize, SEEK_CUR);
1208             lSize = 1; //sizeof(bool);
1209             fseek ( tfile, lSize, SEEK_CUR);
1210             lSize = sizeof(int);
1211             fseek ( tfile, lSize, SEEK_CUR);
1212             lSize = sizeof(int);
1213             fseek ( tfile, lSize, SEEK_CUR);
1214             lSize = 1; //sizeof(bool);
1215             fseek ( tfile, lSize, SEEK_CUR);
1216             lSize = sizeof(int);
1217             fseek ( tfile, lSize, SEEK_CUR);
1218             if (joints[i].hasparent)
1219                 joints[i].parent = &joints[parentID];
1220             joints[i].velocity = 0;
1221             joints[i].oldposition = joints[i].position;
1222         }
1223         funpackf(tfile, "Bi", &num_muscles);
1224         //muscles = new Muscle[num_muscles];
1225         for (i = 0; i < num_muscles; i++) {
1226             lSize = sizeof(float);
1227             fseek ( tfile, lSize, SEEK_CUR);
1228             lSize = sizeof(float);
1229             fseek ( tfile, lSize, SEEK_CUR);
1230             lSize = sizeof(float);
1231             fseek ( tfile, lSize, SEEK_CUR);
1232             lSize = sizeof(float);
1233             fseek ( tfile, lSize, SEEK_CUR);
1234             lSize = sizeof(float);
1235             fseek ( tfile, lSize, SEEK_CUR);
1236             lSize = sizeof(int);
1237             fseek ( tfile, lSize, SEEK_CUR);
1238             tempmuscle = muscles[i].numverticeslow;
1239             funpackf(tfile, "Bi", &muscles[i].numverticeslow);
1240             if (muscles[i].numverticeslow) {
1241                 //muscles[i].verticeslow.clear();
1242                 //muscles[i].verticeslow.resize(muscles[i].numverticeslow);
1243                 //if(muscles[i].verticeslow)dealloc2(muscles[i].verticeslow);
1244                 muscles[i].verticeslow = (int*)malloc(sizeof(int) * muscles[i].numverticeslow);
1245                 edit = 0;
1246                 for (j = 0; j < muscles[i].numverticeslow - edit; j++) {
1247                     funpackf(tfile, "Bi", &muscles[i].verticeslow[j + edit]);
1248                     if (muscles[i].verticeslow[j + edit] >= modellow.vertexNum) {
1249                         muscles[i].numverticeslow--;
1250                         edit--;
1251                     }
1252                 }
1253
1254
1255             }
1256             lSize = 1; //sizeof(bool);
1257             fseek ( tfile, lSize, SEEK_CUR);
1258             lSize = sizeof(int);
1259             fseek ( tfile, lSize, SEEK_CUR);
1260             fseek ( tfile, lSize, SEEK_CUR);
1261         }
1262         lSize = sizeof(int);
1263         for (j = 0; j < num_muscles; j++) {
1264             for (i = 0; i < muscles[j].numverticeslow; i++) {
1265                 if (muscles[j].numverticeslow && muscles[j].verticeslow[i] < modellow.vertexNum)
1266                     modellow.owner[muscles[j].verticeslow[i]] = j;
1267             }
1268         }
1269         /*FindForwards();
1270         for(i=0;i<num_joints;i++){
1271         joints[i].startpos=joints[i].position;
1272         }
1273         for(i=0;i<num_muscles;i++){
1274         FindRotationMuscle(i,-1);
1275         }*/
1276         for (i = 0; i < modellow.vertexNum; i++) {
1277             modellow.vertex[i] = modellow.vertex[i] - (muscles[modellow.owner[i]].parent1->position + muscles[modellow.owner[i]].parent2->position) / 2;
1278             glMatrixMode(GL_MODELVIEW);                                                 // Select The Modelview Matrix
1279             glPushMatrix();
1280             glLoadIdentity();
1281             glRotatef(muscles[modellow.owner[i]].rotate3, 0, 1, 0);
1282             glRotatef(muscles[modellow.owner[i]].rotate2 - 90, 0, 0, 1);
1283             glRotatef(muscles[modellow.owner[i]].rotate1 - 90, 0, 1, 0);
1284             glTranslatef(modellow.vertex[i].x, modellow.vertex[i].y, modellow.vertex[i].z);
1285             glGetFloatv(GL_MODELVIEW_MATRIX, M);
1286             modellow.vertex[i].x = M[12];
1287             modellow.vertex[i].y = M[13];
1288             modellow.vertex[i].z = M[14];
1289             glPopMatrix();
1290         }
1291         modellow.CalculateNormals(0);
1292     }
1293
1294     if (clothes) {
1295         tfile = fopen( ConvertFileName(clothesfilename), "rb" );
1296         lSize = sizeof(num_joints);
1297         fseek ( tfile, lSize, SEEK_CUR);
1298         //joints = new Joint[num_joints];
1299         //jointlabels = new int[num_joints];
1300         for (i = 0; i < num_joints; i++) {
1301             lSize = sizeof(XYZ);
1302             fseek ( tfile, lSize, SEEK_CUR);
1303             lSize = sizeof(float);
1304             fseek ( tfile, lSize, SEEK_CUR);
1305             lSize = sizeof(float);
1306             fseek ( tfile, lSize, SEEK_CUR);
1307             lSize = 1; //sizeof(bool);
1308             fseek ( tfile, lSize, SEEK_CUR);
1309             lSize = 1; //sizeof(bool);
1310             fseek ( tfile, lSize, SEEK_CUR);
1311             lSize = sizeof(int);
1312             fseek ( tfile, lSize, SEEK_CUR);
1313             lSize = 1; //sizeof(bool);
1314             fseek ( tfile, lSize, SEEK_CUR);
1315             lSize = 1; //sizeof(bool);
1316             fseek ( tfile, lSize, SEEK_CUR);
1317             lSize = sizeof(int);
1318             fseek ( tfile, lSize, SEEK_CUR);
1319             lSize = sizeof(int);
1320             fseek ( tfile, lSize, SEEK_CUR);
1321             lSize = 1; //sizeof(bool);
1322             fseek ( tfile, lSize, SEEK_CUR);
1323             lSize = sizeof(int);
1324             fseek ( tfile, lSize, SEEK_CUR);
1325             if (joints[i].hasparent)
1326                 joints[i].parent = &joints[parentID];
1327             joints[i].velocity = 0;
1328             joints[i].oldposition = joints[i].position;
1329         }
1330         funpackf(tfile, "Bi", &num_muscles);
1331         //muscles = new Muscle[num_muscles];
1332         for (i = 0; i < num_muscles; i++) {
1333             lSize = sizeof(float);
1334             fseek ( tfile, lSize, SEEK_CUR);
1335             lSize = sizeof(float);
1336             fseek ( tfile, lSize, SEEK_CUR);
1337             lSize = sizeof(float);
1338             fseek ( tfile, lSize, SEEK_CUR);
1339             lSize = sizeof(float);
1340             fseek ( tfile, lSize, SEEK_CUR);
1341             lSize = sizeof(float);
1342             fseek ( tfile, lSize, SEEK_CUR);
1343             lSize = sizeof(int);
1344             fseek ( tfile, lSize, SEEK_CUR);
1345             tempmuscle = muscles[i].numverticesclothes;
1346             funpackf(tfile, "Bi", &muscles[i].numverticesclothes);
1347             if (muscles[i].numverticesclothes) {
1348                 //muscles[i].verticesclothes.clear();
1349                 //muscles[i].verticesclothes.resize(muscles[i].numverticesclothes);
1350                 //if(muscles[i].verticesclothes)dealloc2(muscles[i].verticesclothes);
1351                 muscles[i].verticesclothes = (int*)malloc(sizeof(int) * muscles[i].numverticesclothes);
1352                 edit = 0;
1353                 for (j = 0; j < muscles[i].numverticesclothes - edit; j++) {
1354                     funpackf(tfile, "Bi", &muscles[i].verticesclothes[j + edit]);
1355                     if (muscles[i].verticesclothes[j + edit] >= modelclothes.vertexNum) {
1356                         muscles[i].numverticesclothes--;
1357                         edit--;
1358                     }
1359                 }
1360             }
1361             lSize = 1; //sizeof(bool);
1362             fseek ( tfile, lSize, SEEK_CUR);
1363             lSize = sizeof(int);
1364             fseek ( tfile, lSize, SEEK_CUR);
1365             fseek ( tfile, lSize, SEEK_CUR);
1366         }
1367         lSize = sizeof(int);
1368         for (j = 0; j < num_muscles; j++) {
1369             for (i = 0; i < muscles[j].numverticesclothes; i++) {
1370                 if (muscles[j].numverticesclothes && muscles[j].verticesclothes[i] < modelclothes.vertexNum)
1371                     modelclothes.owner[muscles[j].verticesclothes[i]] = j;
1372             }
1373         }
1374         /*FindForwards();
1375         for(i=0;i<num_joints;i++){
1376         joints[i].startpos=joints[i].position;
1377         }
1378         for(i=0;i<num_muscles;i++){
1379         FindRotationMuscle(i,-1);
1380         }*/
1381         for (i = 0; i < modelclothes.vertexNum; i++) {
1382             modelclothes.vertex[i] = modelclothes.vertex[i] - (muscles[modelclothes.owner[i]].parent1->position + muscles[modelclothes.owner[i]].parent2->position) / 2;
1383             glMatrixMode(GL_MODELVIEW);                                                 // Select The Modelview Matrix
1384             glPushMatrix();
1385             glLoadIdentity();
1386             glRotatef(muscles[modelclothes.owner[i]].rotate3, 0, 1, 0);
1387             glRotatef(muscles[modelclothes.owner[i]].rotate2 - 90, 0, 0, 1);
1388             glRotatef(muscles[modelclothes.owner[i]].rotate1 - 90, 0, 1, 0);
1389             glTranslatef(modelclothes.vertex[i].x, modelclothes.vertex[i].y, modelclothes.vertex[i].z);
1390             glGetFloatv(GL_MODELVIEW_MATRIX, M);
1391             modelclothes.vertex[i].x = M[12];
1392             modelclothes.vertex[i].y = M[13];
1393             modelclothes.vertex[i].z = M[14];
1394             glPopMatrix();
1395         }
1396         modelclothes.CalculateNormals(0);
1397     }
1398     fclose(tfile);
1399
1400     for (i = 0; i < num_joints; i++) {
1401         for (j = 0; j < num_joints; j++) {
1402             if (joints[i].label == j)
1403                 jointlabels[j] = i;
1404         }
1405     }
1406
1407     free = 0;
1408 }
1409
1410 Animation::Animation()
1411 {
1412     numframes = 0;
1413     height = 0;
1414     attack = 0;
1415     joints = 0;
1416     weapontargetnum = 0;
1417
1418     position = 0;
1419     twist = 0;
1420     twist2 = 0;
1421     speed = 0;
1422     onground = 0;
1423     forward = 0;
1424     label = 0;
1425     weapontarget = 0;
1426 }
1427
1428 Animation::~Animation()
1429 {
1430     deallocate();
1431 }
1432
1433 void Animation::deallocate()
1434 {
1435     int i = 0;
1436
1437     if (position) {
1438         for (i = 0; i < joints; i++)
1439             dealloc2(position[i]);
1440
1441         dealloc2(position);
1442     }
1443     position = 0;
1444
1445     if (twist) {
1446         for (i = 0; i < joints; i++)
1447             dealloc2(twist[i]);
1448
1449         dealloc2(twist);
1450     }
1451     twist = 0;
1452
1453     if (twist2) {
1454         for (i = 0; i < joints; i++)
1455             dealloc2(twist2[i]);
1456
1457         dealloc2(twist2);
1458     }
1459     twist2 = 0;
1460
1461     if (onground) {
1462         for (i = 0; i < joints; i++)
1463             dealloc2(onground[i]);
1464
1465         dealloc2(onground);
1466     }
1467     onground = 0;
1468
1469     if (speed)
1470         dealloc2(speed);
1471     speed = 0;
1472
1473     if (forward)
1474         dealloc2(forward);
1475     forward = 0;
1476
1477     if (weapontarget)
1478         dealloc2(weapontarget);
1479     weapontarget = 0;
1480
1481     if (label)
1482         dealloc2(label);
1483     label = 0;
1484
1485     joints = 0;
1486 }
1487
1488 Skeleton::Skeleton()
1489 {
1490     num_joints = 0;
1491
1492     num_muscles = 0;
1493
1494     selected = 0;
1495
1496     memset(forwardjoints, 0, sizeof(forwardjoints));
1497     //          XYZ forward;
1498
1499     id = 0;
1500
1501     memset(lowforwardjoints, 0, sizeof(lowforwardjoints));
1502     //          XYZ lowforward;
1503
1504     //          XYZ specialforward[5];
1505     memset(jointlabels, 0, sizeof(jointlabels));
1506
1507     //          Model model[7];
1508     //          Model modellow;
1509     //          Model modelclothes;
1510     num_models = 0;
1511
1512     //          Model drawmodel;
1513     //          Model drawmodellow;
1514     //          Model drawmodelclothes;
1515
1516     clothes = 0;
1517     spinny = 0;
1518
1519     memset(skinText, 0, sizeof(skinText));
1520     skinsize = 0;
1521
1522     checkdelay = 0;
1523
1524     longdead = 0;
1525     broken = 0;
1526
1527     free = 0;
1528     oldfree = 0;
1529     freetime = 0;
1530     freefall = 0;
1531
1532     joints = 0;
1533     muscles = 0;
1534 }
1535
1536 Skeleton::~Skeleton()
1537 {
1538     if (muscles) {
1539         delete [] muscles;
1540     }
1541     muscles = 0;
1542
1543     if (joints) {
1544         delete [] joints;
1545     }
1546     joints = 0;
1547 }
1548
1549 Muscle::Muscle()
1550 {
1551     vertices = 0;
1552     verticeslow = 0;
1553     verticesclothes = 0;
1554
1555     numvertices = 0;
1556     numverticeslow = 0;
1557     numverticesclothes = 0;
1558     length = 0;
1559     targetlength = 0;
1560     parent1 = 0;
1561     parent2 = 0;
1562     maxlength = 0;
1563     minlength = 0;
1564     type = 0;
1565     visible = 0;
1566     rotate1 = 0, rotate2 = 0, rotate3 = 0;
1567     lastrotate1 = 0, lastrotate2 = 0, lastrotate3 = 0;
1568     oldrotate1 = 0, oldrotate2 = 0, oldrotate3 = 0;
1569     newrotate1 = 0, newrotate2 = 0, newrotate3 = 0;
1570
1571     strength = 0;
1572 }
1573
1574 Muscle::~Muscle()
1575 {
1576     dealloc2(vertices);
1577     dealloc2(verticeslow);
1578     dealloc2(verticesclothes);
1579 }
1580
1581 Animation & Animation::operator = (const Animation & ani)
1582 {
1583     int i = 0;
1584
1585     bool allocate = true;
1586
1587     allocate = ((ani.numframes != numframes) || (ani.joints != joints));
1588
1589     if (allocate)
1590         deallocate();
1591
1592     numframes = ani.numframes;
1593     height = ani.height;
1594     attack = ani.attack;
1595     joints = ani.joints;
1596     weapontargetnum = ani.weapontargetnum;
1597
1598     if (allocate)
1599         position = (XYZ**)malloc(sizeof(XYZ*)*ani.joints);
1600     for (i = 0; i < ani.joints; i++) {
1601         if (allocate)
1602             position[i] = (XYZ*)malloc(sizeof(XYZ) * ani.numframes);
1603         memcpy(position[i], ani.position[i], sizeof(XYZ)*ani.numframes);
1604     }
1605
1606     if (allocate)
1607         twist = (float**)malloc(sizeof(float*)*ani.joints);
1608     for (i = 0; i < ani.joints; i++) {
1609         if (allocate)
1610             twist[i] = (float*)malloc(sizeof(float) * ani.numframes);
1611         memcpy(twist[i], ani.twist[i], sizeof(float)*ani.numframes);
1612     }
1613
1614     if (allocate)
1615         twist2 = (float**)malloc(sizeof(float*)*ani.joints);
1616     for (i = 0; i < ani.joints; i++) {
1617         if (allocate)
1618             twist2[i] = (float*)malloc(sizeof(float) * ani.numframes);
1619         memcpy(twist2[i], ani.twist2[i], sizeof(float)*ani.numframes);
1620     }
1621
1622     if (allocate)
1623         speed = (float*)malloc(sizeof(float) * ani.numframes);
1624     memcpy(speed, ani.speed, sizeof(float)*ani.numframes);
1625
1626     if (allocate)
1627         onground = (bool**)malloc(sizeof(bool*)*ani.joints);
1628     for (i = 0; i < ani.joints; i++) {
1629         if (allocate)
1630             onground[i] = (bool*)malloc(sizeof(bool) * ani.numframes);
1631         memcpy(onground[i], ani.onground[i], sizeof(bool)*ani.numframes);
1632     }
1633
1634     if (allocate)
1635         forward = (XYZ*)malloc(sizeof(XYZ) * ani.numframes);
1636     memcpy(forward, ani.forward, sizeof(XYZ)*ani.numframes);
1637
1638     if (allocate)
1639         weapontarget = (XYZ*)malloc(sizeof(XYZ) * ani.numframes);
1640     memcpy(weapontarget, ani.weapontarget, sizeof(XYZ)*ani.numframes);
1641
1642     if (allocate)
1643         label = (int*)malloc(sizeof(int) * ani.numframes);
1644     memcpy(label, ani.label, sizeof(int)*ani.numframes);
1645
1646     return (*this);
1647 }
1648