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