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