+ if(debugmode){
+ if(Input::isKeyPressed(SDLK_h)){
+ player[0].damagetolerance=200000;
+ player[0].damage=0;
+ player[0].burnt=0;
+ player[0].permanentdamage=0;
+ player[0].superpermanentdamage=0;
+ }
+
+ if(Input::isKeyPressed(SDLK_j)){
+ environment++;
+ if(environment>2)
+ environment=0;
+ Setenvironment(environment);
+ }
+
+ if(Input::isKeyPressed(SDLK_c)){
+ cameramode=1-cameramode;
+ }
+
+ if(Input::isKeyPressed(SDLK_x)&&!Input::isKeyDown(SDLK_LSHIFT)){
+ if(player[0].num_weapons>0){
+ if(weapons.type[player[0].weaponids[0]]==sword)weapons.type[player[0].weaponids[0]]=staff;
+ else if(weapons.type[player[0].weaponids[0]]==staff)weapons.type[player[0].weaponids[0]]=knife;
+ else weapons.type[player[0].weaponids[0]]=sword;
+ if(weapons.type[player[0].weaponids[0]]==sword){
+ weapons.mass[player[0].weaponids[0]]=1.5;
+ weapons.tipmass[player[0].weaponids[0]]=1;
+ weapons.length[player[0].weaponids[0]]=.8;
+ }
+ if(weapons.type[player[0].weaponids[0]]==staff){
+ weapons.mass[player[0].weaponids[0]]=2;
+ weapons.tipmass[player[0].weaponids[0]]=1;
+ weapons.length[player[0].weaponids[0]]=1.5;
+ }
+
+ if(weapons.type[player[0].weaponids[0]]==knife){
+ weapons.mass[player[0].weaponids[0]]=1;
+ weapons.tipmass[player[0].weaponids[0]]=1.2;
+ weapons.length[player[0].weaponids[0]]=.25;
+ }
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_x)&&Input::isKeyDown(SDLK_LSHIFT)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closest!=-1){
+ if(player[closest].num_weapons){
+ if(weapons.type[player[closest].weaponids[0]]==sword)
+ weapons.type[player[closest].weaponids[0]]=staff;
+ else if(weapons.type[player[closest].weaponids[0]]==staff)
+ weapons.type[player[closest].weaponids[0]]=knife;
+ else weapons.type[player[closest].weaponids[0]]=sword;
+ if(weapons.type[player[closest].weaponids[0]]==sword){
+ weapons.mass[player[closest].weaponids[0]]=1.5;
+ weapons.tipmass[player[closest].weaponids[0]]=1;
+ weapons.length[player[closest].weaponids[0]]=.8;
+ }
+ if(weapons.type[player[0].weaponids[0]]==staff){
+ weapons.mass[player[0].weaponids[0]]=2;
+ weapons.tipmass[player[0].weaponids[0]]=1;
+ weapons.length[player[0].weaponids[0]]=1.5;
+ }
+ if(weapons.type[player[closest].weaponids[0]]==knife){
+ weapons.mass[player[closest].weaponids[0]]=1;
+ weapons.tipmass[player[closest].weaponids[0]]=1.2;
+ weapons.length[player[closest].weaponids[0]]=.25;
+ }
+ }
+ if(!player[closest].num_weapons){
+ player[closest].weaponids[0]=weapons.numweapons;
+ weapons.owner[weapons.numweapons]=closest;
+ weapons.type[weapons.numweapons]=knife;
+ weapons.damage[weapons.numweapons]=0;
+ weapons.numweapons++;
+ player[closest].num_weapons=1;
+ if(weapons.type[player[closest].weaponids[0]]==sword){
+ weapons.mass[player[closest].weaponids[0]]=1.5;
+ weapons.tipmass[player[closest].weaponids[0]]=1;
+ weapons.length[player[closest].weaponids[0]]=.8;
+ }
+ if(weapons.type[player[closest].weaponids[0]]==knife){
+ weapons.mass[player[closest].weaponids[0]]=1;
+ weapons.tipmass[player[closest].weaponids[0]]=1.2;
+ weapons.length[player[closest].weaponids[0]]=.25;
+ }
+ }
+ }
+ }
+
+ if(Input::isKeyDown(SDLK_u)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ player[closest].rotation+=multiplier*50;
+ player[closest].targetrotation=player[closest].rotation;
+ }
+
+
+ if(Input::isKeyPressed(SDLK_o)&&!Input::isKeyDown(SDLK_LSHIFT)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(Input::isKeyDown(SDLK_LCTRL))closest=0;
+
+ if(closest!=-1){
+ player[closest].whichskin++;
+ if(player[closest].whichskin>9)
+ player[closest].whichskin=0;
+ if(player[closest].whichskin>2&&player[closest].creature==wolftype)
+ player[closest].whichskin=0;
+
+ LoadTextureSave(creatureskin[player[closest].creature][player[closest].whichskin],
+ &player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ }
+
+ if(player[closest].numclothes){
+ for(int i=0;i<player[closest].numclothes;i++){
+ tintr=player[closest].clothestintr[i];
+ tintg=player[closest].clothestintg[i];
+ tintb=player[closest].clothestintb[i];
+ AddClothes((char *)player[closest].clothes[i],&player[closest].skeleton.skinText[0]);
+ }
+ player[closest].DoMipmaps();
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_o)&&Input::isKeyDown(SDLK_LSHIFT)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closest!=-1){
+ if(player[closest].creature==wolftype){
+ headprop=player[closest].proportionhead.x/1.1;
+ bodyprop=player[closest].proportionbody.x/1.1;
+ armprop=player[closest].proportionarms.x/1.1;
+ legprop=player[closest].proportionlegs.x/1.1;
+ }
+
+ if(player[closest].creature==rabbittype){
+ headprop=player[closest].proportionhead.x/1.2;
+ bodyprop=player[closest].proportionbody.x/1.05;
+ armprop=player[closest].proportionarms.x/1.00;
+ legprop=player[closest].proportionlegs.x/1.1;
+ }
+
+
+ if(player[closest].creature==rabbittype){
+ player[closest].skeleton.id=closest;
+ player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure Wolf",(char *)":Data:Skeleton:Basic Figure Wolf Low",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Wolf.solid",(char *)":Data:Models:Wolf2.solid",(char *)":Data:Models:Wolf3.solid",(char *)":Data:Models:Wolf4.solid",(char *)":Data:Models:Wolf5.solid",(char *)":Data:Models:Wolf6.solid",(char *)":Data:Models:Wolf7.solid",(char *)":Data:Models:Wolflow.solid",(char *)":Data:Models:Belt.solid",0);
+ LoadTextureSave(":Data:Textures:Wolf.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[closest],&player[closest].skeleton.skinsize);
+ player[closest].whichskin=0;
+ player[closest].creature=wolftype;
+
+ player[closest].proportionhead=1.1;
+ player[closest].proportionbody=1.1;
+ player[closest].proportionarms=1.1;
+ player[closest].proportionlegs=1.1;
+ player[closest].proportionlegs.y=1.1;
+ player[closest].scale=.23*5*player[0].scale;
+
+ player[closest].damagetolerance=300;
+ }
+ else
+ {
+ player[closest].skeleton.id=closest;
+ player[closest].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[closest].skeleton.drawmodel.textureptr,1,&player[closest].skeleton.skinText[0],&player[closest].skeleton.skinsize);
+ player[closest].whichskin=0;
+ player[closest].creature=rabbittype;
+
+ player[closest].proportionhead=1.2;
+ player[closest].proportionbody=1.05;
+ player[closest].proportionarms=1.00;
+ player[closest].proportionlegs=1.1;
+ player[closest].proportionlegs.y=1.05;
+ player[closest].scale=.2*5*player[0].scale;
+
+ player[closest].damagetolerance=200;
+ }
+
+ if(player[closest].creature==wolftype){
+ player[closest].proportionhead=1.1*headprop;
+ player[closest].proportionbody=1.1*bodyprop;
+ player[closest].proportionarms=1.1*armprop;
+ player[closest].proportionlegs=1.1*legprop;
+ }
+
+ if(player[closest].creature==rabbittype){
+ player[closest].proportionhead=1.2*headprop;
+ player[closest].proportionbody=1.05*bodyprop;
+ player[closest].proportionarms=1.00*armprop;
+ player[closest].proportionlegs=1.1*legprop;
+ player[closest].proportionlegs.y=1.05*legprop;
+ }
+
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_b)&&!Input::isKeyDown(SDLK_LSHIFT)){
+ slomo=1-slomo;
+ slomodelay=1000;
+ }
+
+
+ if(((Input::isKeyPressed(SDLK_i)&&!Input::isKeyDown(SDLK_LSHIFT)))){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ XYZ flatfacing2,flatvelocity2;
+ XYZ blah;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(distance<144&&!player[i].headless)
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ blah = player[i].coords;
+ }
+ }
+
+ if(closest!=-1){
+ XYZ headspurtdirection;
+ //int i = player[closest].skeleton.jointlabels[head];
+ Joint& headjoint=playerJoint(closest,head);
+ for(int k=0;k<player[closest].skeleton.num_joints; k++){
+ if(!player[closest].skeleton.free)
+ flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)
+ flatvelocity2=headjoint.velocity;
+ if(!player[closest].skeleton.free)
+ flatfacing2=DoRotation(DoRotation(DoRotation(headjoint.position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)
+ flatfacing2=headjoint.position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ headspurtdirection=headjoint.position-playerJoint(closest,neck).position;
+ Normalise(&headspurtdirection);
+ Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, .6, 1);
+ flatvelocity2+=headspurtdirection*8;
+ Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2/2, 1,1,1, .16, 1);
+ }
+ Sprite::MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
+
+ emit_sound_at(splattersound, blah);
+ emit_sound_at(breaksound2, blah, 100.);
+
+ if(player[closest].skeleton.free==2)player[closest].skeleton.free=0;
+ player[closest].RagDoll(0);
+ player[closest].dead=2;
+ player[closest].headless=1;
+ player[closest].DoBloodBig(3,165);
+
+ camerashake+=.3;
+ }
+ }
+
+ if(((Input::isKeyPressed(SDLK_i)&&Input::isKeyDown(SDLK_LSHIFT)))){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ XYZ flatfacing2,flatvelocity2;
+ XYZ blah;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(distance<144)
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ blah=player[i].coords;
+ }
+ }
+
+ if(closest!=-1){
+ emit_sound_at(splattersound, blah);
+
+ emit_sound_at(breaksound2, blah);
+
+ for(int i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
+ Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .3, 1);
+ Sprite::MakeSprite(cloudsprite, flatfacing2,flatvelocity2*0, .6,0,0, 1, .5);
+ }
+
+ for(int i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2, 1,1,1, 3, 1);
+ Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2, 1,1,1, .4, 1);
+ }
+
+ for(int i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2*2, 1,1,1, 3, 1);
+ Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2*2, 1,1,1, .4, 1);
+ }
+
+ for(int i=0;i<player[closest].skeleton.num_joints; i++){
+ if(!player[closest].skeleton.free)flatvelocity2=player[closest].velocity;
+ if(player[closest].skeleton.free)flatvelocity2=player[closest].skeleton.joints[i].velocity;
+ if(!player[closest].skeleton.free)flatfacing2=DoRotation(DoRotation(DoRotation(player[closest].skeleton.joints[i].position,0,0,player[closest].tilt),player[closest].tilt2,0,0),0,player[closest].rotation,0)*player[closest].scale+player[closest].coords;
+ if(player[closest].skeleton.free)flatfacing2=player[closest].skeleton.joints[i].position*player[closest].scale+player[closest].coords;
+ flatvelocity2.x+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.y+=(float)(abs(Random()%100)-50)/10;
+ flatvelocity2.z+=(float)(abs(Random()%100)-50)/10;
+ Sprite::MakeSprite(bloodflamesprite, flatfacing2,flatvelocity2*2, 1,1,1, 3, 1);
+ Sprite::MakeSprite(bloodsprite, flatfacing2,flatvelocity2*2, 1,1,1, .4, 1);
+ }
+
+ XYZ temppos;
+ for(int j=0;j<numplayers; j++){
+ if(j!=closest){
+ if(findDistancefast(&player[j].coords,&player[closest].coords)<25){
+ player[j].DoDamage((25-findDistancefast(&player[j].coords,&player[closest].coords))*60);
+ if(player[j].skeleton.free==2)
+ player[j].skeleton.free=1;
+ player[j].skeleton.longdead=0;
+ player[j].RagDoll(0);
+ for(int i=0;i<player[j].skeleton.num_joints; i++){
+ temppos=player[j].skeleton.joints[i].position+player[j].coords;
+ if(findDistancefast(&temppos,&player[closest].coords)<25){
+ flatvelocity2=temppos-player[closest].coords;
+ Normalise(&flatvelocity2);
+ player[j].skeleton.joints[i].velocity+=flatvelocity2*((20-findDistancefast(&temppos,&player[closest].coords))*20);
+ }
+ }
+ }
+ }
+ }
+
+ player[closest].DoDamage(10000);
+ player[closest].RagDoll(0);
+ player[closest].dead=2;
+ player[closest].coords=20;
+ player[closest].skeleton.free=2;
+
+ camerashake+=.6;
+
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_f)){
+ player[0].onfire=1-player[0].onfire;
+ if(player[0].onfire){
+ player[0].CatchFire();
+ }
+ if(!player[0].onfire){
+ emit_sound_at(fireendsound, player[0].coords);
+ pause_sound(stream_firesound);
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_n)&&!Input::isKeyDown(SDLK_LCTRL)){
+ //if(!player[0].skeleton.free)player[0].damage+=500;
+ player[0].RagDoll(0);
+ //player[0].spurt=1;
+ //player[0].DoDamage(1000);
+
+ emit_sound_at(whooshsound, player[0].coords, 128.);
+ }
+
+ if(Input::isKeyPressed(SDLK_n)&&Input::isKeyDown(SDLK_LCTRL)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ for(int i=0;i<objects.numobjects;i++){
+ if(objects.type[i]==treeleavestype){
+ objects.scale[i]*=.9;
+ }
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_m)&&Input::isKeyDown(SDLK_LSHIFT)){
+ editorenabled=1-editorenabled;
+ if(editorenabled){
+ player[0].damagetolerance=100000;
+ } else {
+ player[0].damagetolerance=200;
+ }
+ player[0].damage=0; // these lines were in both if and else, but I think they would better fit in the if
+ player[0].permanentdamage=0;
+ player[0].superpermanentdamage=0;
+ player[0].bloodloss=0;
+ player[0].deathbleeding=0;
+ }
+
+ //skip level
+ if(whichlevel!=-2&&Input::isKeyPressed(SDLK_k)&&Input::isKeyDown(SDLK_LSHIFT)&&!editorenabled){
+ targetlevel++;
+ if(targetlevel>numchallengelevels-1)
+ targetlevel=0;
+ loading=1;
+ leveltime=5;
+ }
+
+ if(editorenabled){
+ if(Input::isKeyPressed(SDLK_DELETE)&&Input::isKeyDown(SDLK_LSHIFT)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(numplayers>1)
+ for(int i=1;i<numplayers;i++){
+ distance=findDistancefast(&player[i].coords,&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closestdist>0&&closest>=0){
+ //player[closest]=player[numplayers-1];
+ //player[closest].skeleton=player[numplayers-1].skeleton;
+ numplayers--;
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_DELETE)&&Input::isKeyDown(SDLK_LCTRL)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ if(max_objects>1)
+ for(int i=1;i<max_objects;i++){
+ distance=findDistancefast(&objects.position[i],&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closestdist>0&&closest>=0){
+ objects.position[closest].y-=500;
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_m)&&Input::isKeyDown(SDLK_LSHIFT)){
+ //drawmode++;
+ //if(drawmode>2)drawmode=0;
+ if(objects.numobjects<max_objects-1){
+ XYZ boxcoords;
+ boxcoords.x=player[0].coords.x;
+ boxcoords.z=player[0].coords.z;
+ boxcoords.y=player[0].coords.y-3;
+ if(editortype==bushtype)boxcoords.y=player[0].coords.y-.5;
+ if(editortype==firetype)boxcoords.y=player[0].coords.y-.5;
+ //objects.MakeObject(abs(Random()%3),boxcoords,Random()%360);
+ float temprotat,temprotat2;
+ temprotat=editorrotation;
+ temprotat2=editorrotation2;
+ if(temprotat<0||editortype==bushtype)temprotat=Random()%360;
+ if(temprotat2<0)temprotat2=Random()%360;
+
+ objects.MakeObject(editortype,boxcoords,(int)temprotat-((int)temprotat)%30,(int)temprotat2,editorsize);
+ if(editortype==treetrunktype)
+ objects.MakeObject(treeleavestype,boxcoords,Random()%360*(temprotat2<2)+(int)editorrotation-((int)editorrotation)%30,editorrotation2,editorsize);
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_p)&&Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
+ if(numplayers<maxplayers-1){
+ player[numplayers].scale=.2*5*player[0].scale;
+ player[numplayers].creature=rabbittype;
+ player[numplayers].howactive=editoractive;
+ player[numplayers].skeleton.id=numplayers;
+ player[numplayers].skeleton.Load((char *)":Data:Skeleton:Basic Figure",(char *)":Data:Skeleton:Basic Figurelow",(char *)":Data:Skeleton:Rabbitbelt",(char *)":Data:Models:Body.solid",(char *)":Data:Models:Body2.solid",(char *)":Data:Models:Body3.solid",(char *)":Data:Models:Body4.solid",(char *)":Data:Models:Body5.solid",(char *)":Data:Models:Body6.solid",(char *)":Data:Models:Body7.solid",(char *)":Data:Models:Bodylow.solid",(char *)":Data:Models:Belt.solid",1);
+
+ //texsize=512*512*3/texdetail/texdetail;
+ //if(!player[numplayers].loaded)player[numplayers].skeleton.skinText = new GLubyte[texsize];
+ //player[numplayers].skeleton.skinText.resize(texsize);
+
+ int k=abs(Random()%2)+1;
+ if(k==0){
+ LoadTextureSave(":Data:Textures:Fur3.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ player[numplayers].whichskin=0;
+ }
+ else if(k==1){
+ LoadTextureSave(":Data:Textures:Fur.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ player[numplayers].whichskin=1;
+ }
+ else {
+ LoadTextureSave(":Data:Textures:Fur2.jpg",&player[numplayers].skeleton.drawmodel.textureptr,1,&player[numplayers].skeleton.skinText[0],&player[numplayers].skeleton.skinsize);
+ player[numplayers].whichskin=2;
+ }
+
+ LoadTexture(":Data:Textures:Belt.png",&player[numplayers].skeleton.drawmodelclothes.textureptr,1,1);
+ player[numplayers].power=1;
+ player[numplayers].speedmult=1;
+ player[numplayers].currentanimation=bounceidleanim;
+ player[numplayers].targetanimation=bounceidleanim;
+ player[numplayers].currentframe=0;
+ player[numplayers].targetframe=1;
+ player[numplayers].target=0;
+ player[numplayers].bled=0;
+ player[numplayers].speed=1+(float)(Random()%100)/1000;
+
+ player[numplayers].targetrotation=player[0].targetrotation;
+ player[numplayers].rotation=player[0].rotation;
+
+ player[numplayers].velocity=0;
+ player[numplayers].coords=player[0].coords;
+ player[numplayers].oldcoords=player[numplayers].coords;
+ player[numplayers].realoldcoords=player[numplayers].coords;
+
+ player[numplayers].id=numplayers;
+ player[numplayers].skeleton.id=numplayers;
+ player[numplayers].updatedelay=0;
+ player[numplayers].normalsupdatedelay=0;
+
+ player[numplayers].aitype=passivetype;
+
+ if(player[0].creature==wolftype){
+ headprop=player[0].proportionhead.x/1.1;
+ bodyprop=player[0].proportionbody.x/1.1;
+ armprop=player[0].proportionarms.x/1.1;
+ legprop=player[0].proportionlegs.x/1.1;
+ }
+
+ if(player[0].creature==rabbittype){
+ headprop=player[0].proportionhead.x/1.2;
+ bodyprop=player[0].proportionbody.x/1.05;
+ armprop=player[0].proportionarms.x/1.00;
+ legprop=player[0].proportionlegs.x/1.1;
+ }
+
+ if(player[numplayers].creature==wolftype){
+ player[numplayers].proportionhead=1.1*headprop;
+ player[numplayers].proportionbody=1.1*bodyprop;
+ player[numplayers].proportionarms=1.1*armprop;
+ player[numplayers].proportionlegs=1.1*legprop;
+ }
+
+ if(player[numplayers].creature==rabbittype){
+ player[numplayers].proportionhead=1.2*headprop;
+ player[numplayers].proportionbody=1.05*bodyprop;
+ player[numplayers].proportionarms=1.00*armprop;
+ player[numplayers].proportionlegs=1.1*legprop;
+ player[numplayers].proportionlegs.y=1.05*legprop;
+ }
+
+ player[numplayers].headless=0;
+ player[numplayers].onfire=0;
+
+ if(cellophane){
+ player[numplayers].proportionhead.z=0;
+ player[numplayers].proportionbody.z=0;
+ player[numplayers].proportionarms.z=0;
+ player[numplayers].proportionlegs.z=0;
+ }
+
+ player[numplayers].tempanimation.Load((char *)"Tempanim",0,0);
+
+ player[numplayers].damagetolerance=200;
+
+ player[numplayers].protectionhead=player[0].protectionhead;
+ player[numplayers].protectionhigh=player[0].protectionhigh;
+ player[numplayers].protectionlow=player[0].protectionlow;
+ player[numplayers].armorhead=player[0].armorhead;
+ player[numplayers].armorhigh=player[0].armorhigh;
+ player[numplayers].armorlow=player[0].armorlow;
+ player[numplayers].metalhead=player[0].metalhead;
+ player[numplayers].metalhigh=player[0].metalhigh;
+ player[numplayers].metallow=player[0].metallow;
+
+ player[numplayers].immobile=player[0].immobile;
+
+ player[numplayers].numclothes=player[0].numclothes;
+ if(player[numplayers].numclothes)
+ for(int i=0;i<player[numplayers].numclothes;i++){
+ strcpy(player[numplayers].clothes[i], player[0].clothes[i]);
+ player[numplayers].clothestintr[i]=player[0].clothestintr[i];
+ player[numplayers].clothestintg[i]=player[0].clothestintg[i];
+ player[numplayers].clothestintb[i]=player[0].clothestintb[i];
+ tintr=player[numplayers].clothestintr[i];
+ tintg=player[numplayers].clothestintg[i];
+ tintb=player[numplayers].clothestintb[i];
+ AddClothes((char *)player[numplayers].clothes[i],&player[numplayers].skeleton.skinText[0]);
+ }
+ if(player[numplayers].numclothes){
+ player[numplayers].DoMipmaps();
+ }
+
+ player[numplayers].power=player[0].power;
+ player[numplayers].speedmult=player[0].speedmult;
+
+ player[numplayers].damage=0;
+ player[numplayers].permanentdamage=0;
+ player[numplayers].superpermanentdamage=0;
+ player[numplayers].deathbleeding=0;
+ player[numplayers].bleeding=0;
+ player[numplayers].numwaypoints=0;
+ player[numplayers].waypoint=0;
+ player[numplayers].jumppath=0;
+ player[numplayers].weaponstuck=-1;
+ player[numplayers].weaponactive=-1;
+ player[numplayers].num_weapons=0;
+ player[numplayers].bloodloss=0;
+ player[numplayers].dead=0;
+
+ player[numplayers].loaded=1;
+
+ numplayers++;
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_p)&&Input::isKeyDown(SDLK_LSHIFT)){
+ if(player[numplayers-1].numwaypoints<90){
+ player[numplayers-1].waypoints[player[numplayers-1].numwaypoints]=player[0].coords;
+ player[numplayers-1].waypointtype[player[numplayers-1].numwaypoints]=editorpathtype;
+ player[numplayers-1].numwaypoints++;
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_p)&&Input::isKeyDown(SDLK_LCTRL)){
+ if(numpathpoints<30){
+ bool connected,alreadyconnected;
+ connected=0;
+ if(numpathpoints>1)
+ for(int i=0;i<numpathpoints;i++){
+ if(findDistancefast(&pathpoint[i],&player[0].coords)<.5&&i!=pathpointselected&&!connected){
+ alreadyconnected=0;
+ for(int j=0;j<numpathpointconnect[pathpointselected];j++){
+ if(pathpointconnect[pathpointselected][j]==i)alreadyconnected=1;
+ }
+ if(!alreadyconnected){
+ numpathpointconnect[pathpointselected]++;
+ connected=1;
+ pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected]-1]=i;
+ }
+ }
+ }
+ if(!connected){
+ numpathpoints++;
+ pathpoint[numpathpoints-1]=player[0].coords;
+ numpathpointconnect[numpathpoints-1]=0;
+ if(numpathpoints>1&&pathpointselected!=-1){
+ numpathpointconnect[pathpointselected]++;
+ pathpointconnect[pathpointselected][numpathpointconnect[pathpointselected]-1]=numpathpoints-1;
+ }
+ pathpointselected=numpathpoints-1;
+ }
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_PERIOD)){
+ pathpointselected++;
+ if(pathpointselected>=numpathpoints)
+ pathpointselected=-1;
+ }
+ if(Input::isKeyPressed(SDLK_COMMA)&&!Input::isKeyDown(SDLK_LSHIFT)){
+ pathpointselected--;
+ if(pathpointselected<=-2)
+ pathpointselected=numpathpoints-1;
+ }
+ if(Input::isKeyPressed(SDLK_COMMA)&&Input::isKeyDown(SDLK_LSHIFT)){
+ if(pathpointselected!=-1){
+ numpathpoints--;
+ pathpoint[pathpointselected]=pathpoint[numpathpoints];
+ numpathpointconnect[pathpointselected]=numpathpointconnect[numpathpoints];
+ for(int i=0;i<numpathpointconnect[pathpointselected];i++){
+ pathpointconnect[pathpointselected][i]=pathpointconnect[numpathpoints][i];
+ }
+ for(int i=0;i<numpathpoints;i++){
+ for(int j=0;j<numpathpointconnect[i];j++){
+ if(pathpointconnect[i][j]==pathpointselected){
+ pathpointconnect[i][j]=pathpointconnect[i][numpathpointconnect[i]-1];
+ numpathpointconnect[i]--;
+ }
+ if(pathpointconnect[i][j]==numpathpoints){
+ pathpointconnect[i][j]=pathpointselected;
+ }
+ }
+ }
+ pathpointselected=numpathpoints-1;
+ }
+ }
+
+ if(Input::isKeyPressed(SDLK_LEFT)&&Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
+ editortype--;
+ if(editortype==treeleavestype||editortype==10)editortype--;
+ if(editortype<0)editortype=firetype;
+ }
+
+ if(Input::isKeyPressed(SDLK_RIGHT)&&Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
+ editortype++;
+ if(editortype==treeleavestype||editortype==10)editortype++;
+ if(editortype>firetype)editortype=0;
+ }
+
+ if(Input::isKeyDown(SDLK_LEFT)&&!Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
+ editorrotation-=multiplier*100;
+ if(editorrotation<-.01)editorrotation=-.01;
+ }
+
+ if(Input::isKeyDown(SDLK_RIGHT)&&!Input::isKeyDown(SDLK_LSHIFT)&&!Input::isKeyDown(SDLK_LCTRL)){
+ editorrotation+=multiplier*100;
+ }
+
+ if(Input::isKeyDown(SDLK_UP)&&!Input::isKeyDown(SDLK_LCTRL)){
+ editorsize+=multiplier;
+ }
+
+ if(Input::isKeyDown(SDLK_DOWN)&&!Input::isKeyDown(SDLK_LCTRL)){
+ editorsize-=multiplier;
+ if(editorsize<.1)editorsize=.1;
+ }
+
+
+ if(Input::isKeyPressed(SDLK_LEFT)&&Input::isKeyDown(SDLK_LSHIFT)&&Input::isKeyDown(SDLK_LCTRL)){
+ mapradius-=multiplier*10;
+ }
+
+ if(Input::isKeyPressed(SDLK_RIGHT)&&Input::isKeyDown(SDLK_LSHIFT)&&Input::isKeyDown(SDLK_LCTRL)){
+ mapradius+=multiplier*10;
+ }
+ if(Input::isKeyDown(SDLK_UP)&&Input::isKeyDown(SDLK_LCTRL)){
+ editorrotation2+=multiplier*100;
+ }
+
+ if(Input::isKeyDown(SDLK_DOWN)&&Input::isKeyDown(SDLK_LCTRL)){
+ editorrotation2-=multiplier*100;
+ if(editorrotation2<-.01)editorrotation2=-.01;
+ }
+ if(Input::isKeyPressed(SDLK_DELETE)&&objects.numobjects&&Input::isKeyDown(SDLK_LSHIFT)){
+ int closest=-1;
+ float closestdist=-1;
+ float distance;
+ for(int i=0;i<objects.numobjects;i++){
+ distance=findDistancefast(&objects.position[i],&player[0].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=i;
+ }
+ }
+ if(closestdist>0&&closest>=0)objects.DeleteObject(closest);
+ }
+ }
+ }
+}
+
+
+
+void Game::doJumpReversals(){
+ for(int k=0;k<numplayers;k++)
+ for(int i=k;i<numplayers;i++){
+ if(i==k)continue;
+ if( player[k].skeleton.free==0&&
+ player[i].skeleton.oldfree==0&&
+ (player[i].targetanimation==jumpupanim||
+ player[k].targetanimation==jumpupanim)&&
+ (player[i].aitype==playercontrolled||
+ player[k].aitype==playercontrolled)&&
+ (player[i].aitype==attacktypecutoff&&player[i].stunned<=0||
+ player[k].aitype==attacktypecutoff&&player[k].stunned<=0)){
+ if( findDistancefast(&player[i].coords,&player[k].coords)<10*sq((player[i].scale+player[k].scale)*2.5)&&
+ findDistancefastflat(&player[i].coords,&player[k].coords)<2*sq((player[i].scale+player[k].scale)*2.5)){
+ //TODO: refactor two huge similar ifs
+ if(player[i].targetanimation==jumpupanim&&
+ player[k].targetanimation!=getupfrombackanim&&
+ player[k].targetanimation!=getupfromfrontanim&&
+ animation[player[k].targetanimation].height==middleheight&&
+ normaldotproduct(player[i].velocity,player[k].coords-player[i].coords)<0&&
+ (player[k].aitype==playercontrolled&&player[k].attackkeydown||
+ player[k].aitype!=playercontrolled)){
+ player[i].victim=&player[k];
+ player[i].velocity=0;
+ player[i].currentanimation=jumpreversedanim;
+ player[i].targetanimation=jumpreversedanim;
+ player[i].currentframe=0;
+ player[i].targetframe=1;
+ player[i].targettilt2=0;
+ player[k].victim=&player[i];
+ player[k].velocity=0;
+ player[k].currentanimation=jumpreversalanim;
+ player[k].targetanimation=jumpreversalanim;
+ player[k].currentframe=0;
+ player[k].targetframe=1;
+ player[k].targettilt2=0;
+ if(player[i].coords.y<player[k].coords.y+1){
+ player[i].currentanimation=rabbitkickreversedanim;
+ player[i].targetanimation=rabbitkickreversedanim;
+ player[i].currentframe=1;
+ player[i].targetframe=2;
+ player[k].currentanimation=rabbitkickreversalanim;
+ player[k].targetanimation=rabbitkickreversalanim;
+ player[k].currentframe=1;
+ player[k].targetframe=2;
+ }
+ player[i].target=0;
+ player[k].oldcoords=player[k].coords;
+ player[i].coords=player[k].coords;
+ player[k].targetrotation=player[i].targetrotation;
+ player[k].rotation=player[i].targetrotation;
+ if(player[k].aitype==attacktypecutoff)
+ player[k].stunned=.5;
+ }
+ if(player[k].targetanimation==jumpupanim&&
+ player[i].targetanimation!=getupfrombackanim&&
+ player[i].targetanimation!=getupfromfrontanim&&
+ animation[player[i].targetanimation].height==middleheight&&
+ normaldotproduct(player[k].velocity,player[i].coords-player[k].coords)<0&&
+ ((player[i].aitype==playercontrolled&&player[i].attackkeydown)||
+ player[i].aitype!=playercontrolled)){
+ player[k].victim=&player[i];
+ player[k].velocity=0;
+ player[k].currentanimation=jumpreversedanim;
+ player[k].targetanimation=jumpreversedanim;
+ player[k].currentframe=0;
+ player[k].targetframe=1;
+ player[k].targettilt2=0;
+ player[i].victim=&player[k];
+ player[i].velocity=0;
+ player[i].currentanimation=jumpreversalanim;
+ player[i].targetanimation=jumpreversalanim;
+ player[i].currentframe=0;
+ player[i].targetframe=1;
+ player[i].targettilt2=0;
+ if(player[k].coords.y<player[i].coords.y+1){
+ player[k].targetanimation=rabbitkickreversedanim;
+ player[k].currentanimation=rabbitkickreversedanim;
+ player[i].currentanimation=rabbitkickreversalanim;
+ player[i].targetanimation=rabbitkickreversalanim;
+ player[k].currentframe=1;
+ player[k].targetframe=2;
+ player[i].currentframe=1;
+ player[i].targetframe=2;
+ }
+ player[k].target=0;
+ player[i].oldcoords=player[i].coords;
+ player[k].coords=player[i].coords;
+ player[i].targetrotation=player[k].targetrotation;
+ player[i].rotation=player[k].targetrotation;
+ if(player[i].aitype==attacktypecutoff)
+ player[i].stunned=.5;
+ }
+ }
+ }
+ }
+}
+
+void Game::doAerialAcrobatics(){
+ static XYZ facing,flatfacing;
+ for(int k=0;k<numplayers;k++){
+ player[k].turnspeed=500;
+
+ if((player[k].isRun()&&
+ ((player[k].targetrotation!=rabbitrunninganim&&
+ player[k].targetrotation!=wolfrunninganim)||
+ player[k].targetframe==4))||
+ player[k].targetanimation==removeknifeanim||
+ player[k].targetanimation==crouchremoveknifeanim||
+ player[k].targetanimation==flipanim||
+ player[k].targetanimation==fightsidestep||
+ player[k].targetanimation==walkanim){
+ player[k].rotation=stepTowardf(player[k].rotation, player[k].targetrotation, multiplier*player[k].turnspeed);
+ }
+
+
+ if(player[k].isStop()||
+ player[k].isLanding()||
+ player[k].targetanimation==staggerbackhighanim||
+ (player[k].targetanimation==sneakanim&&player[k].currentanimation==sneakanim)||
+ player[k].targetanimation==staggerbackhardanim||
+ player[k].targetanimation==backhandspringanim||
+ player[k].targetanimation==dodgebackanim||
+ player[k].targetanimation==rollanim||
+ (animation[player[k].targetanimation].attack&&
+ player[k].targetanimation!=rabbitkickanim&&
+ (player[k].targetanimation!=crouchstabanim||player[k].hasvictim)&&
+ (player[k].targetanimation!=swordgroundstabanim||player[k].hasvictim))){
+ player[k].rotation=stepTowardf(player[k].rotation, player[k].targetrotation, multiplier*player[k].turnspeed*2);
+ }
+
+ if(player[k].targetanimation==sneakanim&&player[k].currentanimation!=sneakanim){
+ player[k].rotation=stepTowardf(player[k].rotation, player[k].targetrotation, multiplier*player[k].turnspeed*4);
+ }
+
+ /*if(player[k].aitype!=passivetype||(findDistancefast(&player[k].coords,&viewer)<viewdistance*viewdistance))*/
+ player[k].DoStuff();
+ if(player[k].immobile&&k!=0)
+ player[k].coords=player[k].realoldcoords;
+
+ //if player's position has changed (?)
+ if(findDistancefast(&player[k].coords,&player[k].realoldcoords)>0&&
+ !player[k].skeleton.free&&
+ player[k].targetanimation!=climbanim&&
+ player[k].targetanimation!=hanganim){
+ XYZ lowpoint,lowpointtarget,lowpoint2,lowpointtarget2,lowpoint3,lowpointtarget3,lowpoint4,lowpointtarget4,lowpoint5,lowpointtarget5,lowpoint6,lowpointtarget6,lowpoint7,lowpointtarget7,colpoint,colpoint2;
+ int whichhit;
+ bool tempcollide=0;
+
+ if(player[k].collide<-.3)
+ player[k].collide=-.3;
+ if(player[k].collide>1)
+ player[k].collide=1;
+ player[k].collide-=multiplier*30;
+
+ //clip to terrain
+ player[k].coords.y=max(player[k].coords.y, terrain.getHeight(player[k].coords.x,player[k].coords.z));
+
+ for(int l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ int i=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ if(objects.type[i]!=rocktype||
+ objects.scale[i]>.5&&player[k].aitype==playercontrolled||
+ objects.position[i].y>player[k].coords.y){
+ lowpoint=player[k].coords;
+ if(player[k].targetanimation!=jumpupanim&&
+ player[k].targetanimation!=jumpdownanim&&
+ !player[k].isFlip())
+ lowpoint.y+=1.25;
+ else
+ lowpoint.y+=1.3;
+ if( player[k].coords.y<terrain.getHeight(player[k].coords.x,player[k].coords.z)&&
+ player[k].coords.y>terrain.getHeight(player[k].coords.x,player[k].coords.z)-.1)
+ player[k].coords.y=terrain.getHeight(player[k].coords.x,player[k].coords.z);
+ if(player[k].SphereCheck(&lowpoint, 1.3, &colpoint, &objects.position[i], &objects.rotation[i], &objects.model[i])!=-1){
+ flatfacing=lowpoint-player[k].coords;
+ player[k].coords=lowpoint;
+ player[k].coords.y-=1.3;
+ player[k].collide=1;
+ tempcollide=1;
+ //wall jumps
+ //TODO: refactor four similar blocks
+ if(player[k].aitype==playercontrolled&&
+ (player[k].targetanimation==jumpupanim||
+ player[k].targetanimation==jumpdownanim||
+ player[k].isFlip())&&
+ !player[k].jumptogglekeydown&&
+ player[k].jumpkeydown){
+ lowpointtarget=lowpoint+DoRotation(player[k].facing,0,-90,0)*1.5;
+ XYZ tempcoords1=lowpoint;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
+ setAnimation(k,walljumpleftanim);
+ emit_sound_at(movewhooshsound, player[k].coords);
+ if(k==0)
+ pause_sound(whooshsound);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
+ if(lowpointtarget.z<0)
+ player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)
+ numwallflipped++;
+ }
+ else
+ {
+ lowpoint=tempcoords1;
+ lowpointtarget=lowpoint+DoRotation(player[k].facing,0,90,0)*1.5;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
+ setAnimation(k,walljumprightanim);
+ emit_sound_at(movewhooshsound, player[k].coords);
+ if(k==0)pause_sound(whooshsound);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ else
+ {
+ lowpoint=tempcoords1;
+ lowpointtarget=lowpoint+player[k].facing*2;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
+ setAnimation(k,walljumpbackanim);
+ emit_sound_at(movewhooshsound, player[k].coords);
+ if(k==0)pause_sound(whooshsound);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ else
+ {
+ lowpoint=tempcoords1;
+ lowpointtarget=lowpoint-player[k].facing*2;
+ whichhit=objects.model[i].LineCheck(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1&&fabs(objects.model[i].facenormals[whichhit].y)<.3){
+ setAnimation(k,walljumpfrontanim);
+ emit_sound_at(movewhooshsound, player[k].coords);
+ if(k==0)pause_sound(whooshsound);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
+ if(lowpointtarget.z<0)player[k].rotation=180-player[k].rotation;
+ player[k].rotation+=180;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+ if(k==0)numwallflipped++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if(objects.type[i]==rocktype){
+ lowpoint2=player[k].coords;
+ lowpoint=player[k].coords;
+ lowpoint.y+=2;
+ if(objects.model[i].LineCheck(&lowpoint,&lowpoint2,&colpoint,&objects.position[i],&objects.rotation[i])!=-1){
+ player[k].coords=colpoint;
+ player[k].collide=1;
+ tempcollide=1;
+
+ if(player[k].targetanimation==jumpdownanim||player[k].isFlip()){
+ //flipped into a rock
+ if(player[k].isFlip()&&animation[player[k].targetanimation].label[player[k].targetframe]==7)
+ player[k].RagDoll(0);
+
+ if(player[k].targetanimation==jumpupanim){
+ player[k].jumppower=-4;
+ player[k].targetanimation=player[k].getIdle();
+ }
+ player[k].target=0;
+ player[k].targetframe=0;
+ player[k].onterrain=1;
+
+ if(player[k].id==0){
+ pause_sound(whooshsound);
+ OPENAL_SetVolume(channels[whooshsound], 0);
+ }
+
+ //landing
+ if((player[k].targetanimation==jumpdownanim||player[k].isFlip())&&!player[k].wasLanding()){
+ if(player[k].isFlip())
+ player[k].jumppower=-4;
+ player[k].targetanimation=player[k].getLanding();
+ emit_sound_at(landsound, player[k].coords, 128.);
+ if(k==0){
+ envsound[numenvsounds]=player[k].coords;
+ envsoundvol[numenvsounds]=16;
+ envsoundlife[numenvsounds]=.4;
+ numenvsounds++;
+ }
+
+ }
+ }
+ }
+ }
+ }
+
+ if(tempcollide&&(/*player[k].jumptogglekeydown*/1==1||player[k].aitype!=playercontrolled))
+ for(int l=0;l<terrain.patchobjectnum[player[k].whichpatchx][player[k].whichpatchz];l++){
+ int i=terrain.patchobjects[player[k].whichpatchx][player[k].whichpatchz][l];
+ lowpoint=player[k].coords;
+ lowpoint.y+=1.35;
+ if(objects.type[i]!=rocktype)
+ if(player[k].SphereCheck(&lowpoint,1.33,&colpoint,&objects.position[i],&objects.rotation[i],&objects.model[i])!=-1){
+ if(player[k].targetanimation!=jumpupanim&&
+ player[k].targetanimation!=jumpdownanim&&
+ player[k].onterrain)
+ player[k].avoidcollided=1;
+ player[k].coords=lowpoint;
+ player[k].coords.y-=1.35;
+ player[k].collide=1;
+
+ if((player[k].grabdelay<=0||player[k].aitype!=playercontrolled)&&
+ (player[k].currentanimation!=climbanim&&
+ player[k].currentanimation!=hanganim&&
+ !player[k].isWallJump()||
+ player[k].targetanimation==jumpupanim||
+ player[k].targetanimation==jumpdownanim)){
+ lowpoint=player[k].coords;
+ objects.model[i].SphereCheckPossible(&lowpoint, 1.5, &objects.position[i], &objects.rotation[i]);
+ lowpoint=player[k].coords;
+ lowpoint.y+=.05;
+ facing=0;
+ facing.z=-1;
+ facing=DoRotation(facing,0,player[k].targetrotation+180,0);
+ lowpointtarget=lowpoint+facing*1.4;
+ whichhit=objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(whichhit!=-1){
+ lowpoint=player[k].coords;
+ lowpoint.y+=.1;
+ lowpointtarget=lowpoint+facing*1.4;
+ lowpoint2=lowpoint;
+ lowpointtarget2=lowpointtarget;
+ lowpoint3=lowpoint;
+ lowpointtarget3=lowpointtarget;
+ lowpoint4=lowpoint;
+ lowpointtarget4=lowpointtarget;
+ lowpoint5=lowpoint;
+ lowpointtarget5=lowpointtarget;
+ lowpoint6=lowpoint;
+ lowpointtarget6=lowpointtarget;
+ lowpoint7=lowpoint;
+ lowpointtarget7=lowpoint;
+ lowpoint2.x+=.1;
+ lowpointtarget2.x+=.1;
+ lowpoint3.z+=.1;
+ lowpointtarget3.z+=.1;
+ lowpoint4.x-=.1;
+ lowpointtarget4.x-=.1;
+ lowpoint5.z-=.1;
+ lowpointtarget5.z-=.1;
+ lowpoint6.y+=45/13;
+ lowpointtarget6.y+=45/13;
+ lowpointtarget6+=facing*.6;
+ lowpointtarget7.y+=90/13;
+ whichhit=objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,&colpoint,&objects.position[i],&objects.rotation[i]);
+ if(objects.friction[i]>.5)
+ if(whichhit!=-1){
+ if(whichhit!=-1&&player[k].targetanimation!=jumpupanim&&player[k].targetanimation!=jumpdownanim)
+ player[k].collided=1;
+ if(checkcollide(lowpoint7,lowpointtarget7)==-1)
+ if(checkcollide(lowpoint6,lowpointtarget6)==-1)
+ if( objects.model[i].LineCheckPossible(&lowpoint2,&lowpointtarget2,
+ &colpoint,&objects.position[i],&objects.rotation[i])!=-1&&
+ objects.model[i].LineCheckPossible(&lowpoint3,&lowpointtarget3,
+ &colpoint,&objects.position[i],&objects.rotation[i])!=-1&&
+ objects.model[i].LineCheckPossible(&lowpoint4,&lowpointtarget4,
+ &colpoint,&objects.position[i],&objects.rotation[i])!=-1&&
+ objects.model[i].LineCheckPossible(&lowpoint5,&lowpointtarget5,
+ &colpoint,&objects.position[i],&objects.rotation[i])!=-1)
+ for(int j=0;j<45;j++){
+ lowpoint=player[k].coords;
+ lowpoint.y+=(float)j/13;
+ lowpointtarget=lowpoint+facing*1.4;
+ if(objects.model[i].LineCheckPossible(&lowpoint,&lowpointtarget,
+ &colpoint2,&objects.position[i],&objects.rotation[i])==-1){
+ if(j<=6||j<=25&&player[k].targetanimation==jumpdownanim)
+ break;
+ if(player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim){
+ lowpoint=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[k],0);
+ lowpoint=player[k].coords;
+ lowpoint.y+=(float)j/13;
+ lowpointtarget=lowpoint+facing*1.3;
+ flatfacing=player[k].coords;
+ player[k].coords=colpoint-DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[k],0)*.01;
+ player[k].coords.y=lowpointtarget.y-.07;
+ player[k].currentoffset=(flatfacing-player[k].coords)/player[k].scale;
+
+ if(j>10||!player[k].isRun()){
+ if(player[k].targetanimation==jumpdownanim||player[k].targetanimation==jumpupanim){
+ if(k==0)
+ pause_sound(whooshsound);
+ }
+ emit_sound_at(jumpsound, player[k].coords, 128.);
+
+ lowpointtarget=DoRotation(objects.model[i].facenormals[whichhit],0,objects.rotation[i],0);
+ player[k].rotation=-asin(0-lowpointtarget.x)*180/M_PI;
+ if(lowpointtarget.z<0)
+ player[k].rotation=180-player[k].rotation;
+ player[k].targetrotation=player[k].rotation;
+ player[k].lowrotation=player[k].rotation;
+
+ //player[k].velocity=lowpointtarget*.03;
+ player[k].velocity=0;
+
+ //climb ledge (?)
+ if(player[k].targetanimation==jumpupanim){
+ player[k].targetanimation=climbanim;
+ player[k].jumppower=0;
+ player[k].jumpclimb=1;
+ }
+ player[k].transspeed=6;
+ player[k].target=0;
+ player[k].targetframe=1;
+ //hang ledge (?)
+ if(j>25){
+ setAnimation(k,hanganim);
+ player[k].jumppower=0;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if(player[k].collide<=0){
+ //in the air
+ if(!player[k].onterrain&&
+ player[k].targetanimation!=jumpupanim&&
+ player[k].targetanimation!=jumpdownanim&&
+ player[k].targetanimation!=climbanim&&
+ player[k].targetanimation!=hanganim&&
+ !player[k].isWallJump()&&
+ !player[k].isFlip()){
+ if(player[k].currentanimation!=climbanim&&
+ player[k].currentanimation!=tempanim&&
+ player[k].targetanimation!=backhandspringanim&&
+ (player[k].targetanimation!=rollanim||
+ player[k].targetframe<2||
+ player[k].targetframe>6)){
+ //stagger off ledge (?)
+ if(player[k].targetanimation==staggerbackhighanim||player[k].targetanimation==staggerbackhardanim)
+ player[k].RagDoll(0);
+ setAnimation(k,jumpdownanim);
+
+ if(!k)
+ emit_sound_at(whooshsound, player[k].coords, 128.);
+ }
+ //gravity
+ player[k].velocity.y+=gravity;
+ }
+ }
+ }
+ player[k].realoldcoords=player[k].coords;
+ }
+}
+
+void Game::doAttacks(){
+ static XYZ relative;
+ static int randattack;
+ static bool playerrealattackkeydown=0;
+
+ if(!Input::isKeyDown(attackkey))
+ oldattackkey=0;
+ if(oldattackkey)
+ player[0].attackkeydown=0;
+ if(oldattackkey)
+ playerrealattackkeydown=0;
+ if(!oldattackkey)
+ playerrealattackkeydown=Input::isKeyDown(attackkey);
+ if((player[0].parriedrecently<=0||
+ player[0].weaponactive==-1)&&
+ (!oldattackkey||
+ (realthreat&&
+ player[0].lastattack!=swordslashanim&&
+ player[0].lastattack!=knifeslashstartanim&&
+ player[0].lastattack!=staffhitanim&&
+ player[0].lastattack!=staffspinhitanim)))
+ player[0].attackkeydown=Input::isKeyDown(attackkey);
+ if(Input::isKeyDown(attackkey)&&
+ !oldattackkey&&
+ !player[0].backkeydown){
+ for(int k=0;k<numplayers;k++){
+ if((player[k].targetanimation==swordslashanim||
+ player[k].targetanimation==staffhitanim||
+ player[k].targetanimation==staffspinhitanim)&&
+ player[0].currentanimation!=dodgebackanim&&
+ !player[k].skeleton.free)
+ player[k].Reverse();
+ }
+ }
+
+ if(!hostile||indialogue!=-1)player[0].attackkeydown=0;
+
+ for(int k=0;k<numplayers;k++){
+ if(indialogue!=-1)player[k].attackkeydown=0;
+ if(player[k].targetanimation!=rabbitrunninganim&&player[k].targetanimation!=wolfrunninganim){
+ if(player[k].aitype!=playercontrolled)
+ player[k].victim=&player[0];
+ //attack key pressed
+ if(player[k].attackkeydown){
+ //dodge backward
+ if(player[k].backkeydown&&
+ player[k].targetanimation!=backhandspringanim&&
+ (player[k].isIdle()||
+ player[k].isStop()||
+ player[k].isRun()||
+ player[k].targetanimation==walkanim)){
+ if(player[k].jumppower<=1){
+ player[k].jumppower-=2;
+ }else{
+ for(int i=0;i<numplayers;i++){
+ if(i==k)continue;
+ if(player[i].targetanimation==swordslashanim||
+ player[i].targetanimation==knifeslashstartanim||
+ player[i].targetanimation==staffhitanim||
+ player[i].targetanimation==staffspinhitanim)
+ if(findDistancefast(&player[k].coords,&player[i].coords)<6.5&&!player[i].skeleton.free){
+ setAnimation(k,dodgebackanim);
+ player[k].targetrotation=roughDirectionTo(player[k].coords,player[i].coords);
+ player[k].targettilt2=pitchTo(player[k].coords,player[i].coords);
+ }
+ }
+ if(player[k].targetanimation!=dodgebackanim){
+ if(k==0)numflipped++;
+ setAnimation(k,backhandspringanim);
+ player[k].targetrotation=-rotation+180;
+ if(player[k].leftkeydown)
+ player[k].targetrotation-=45;
+ if(player[k].rightkeydown)
+ player[k].targetrotation+=45;
+ player[k].rotation=player[k].targetrotation;
+ player[k].jumppower-=2;
+ }
+ }
+ }
+ //attack
+ if(!animation[player[k].targetanimation].attack&&
+ !player[k].backkeydown&&
+ (player[k].isIdle()||
+ player[k].isRun()||
+ player[k].targetanimation==walkanim||
+ player[k].targetanimation==sneakanim||
+ player[k].isCrouch())){
+ const int attackweapon=player[k].weaponactive==-1?0:weapons.type[player[k].weaponids[player[k].weaponactive]];
+ //normal attacks (?)
+ player[k].hasvictim=0;
+ if(numplayers>1)
+ for(int i=0;i<numplayers;i++){
+ if(i==k||!(k==0||i==0))continue;
+ if(!player[k].hasvictim)
+ if(animation[player[k].targetanimation].attack!=reversal){
+ //choose an attack
+ const float distance=findDistancefast(&player[k].coords,&player[i].coords);
+ if(distance<4.5&&
+ !player[i].skeleton.free&&
+ player[i].howactive<typedead1&&
+ player[i].targetanimation!=jumpreversedanim&&
+ player[i].targetanimation!=rabbitkickreversedanim&&
+ player[i].targetanimation!=rabbitkickanim&&
+ player[k].targetanimation!=rabbitkickanim&&
+ player[i].targetanimation!=getupfrombackanim&&
+ (player[i].targetanimation!=staggerbackhighanim&&
+ (player[i].targetanimation!=staggerbackhardanim||
+ animation[staggerbackhardanim].label[player[i].targetframe]==6))&&
+ player[i].targetanimation!=jumpdownanim&&
+ player[i].targetanimation!=jumpupanim&&
+ player[i].targetanimation!=getupfromfrontanim){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ if(player[k].aitype==playercontrolled){ //human player
+ //sweep
+ if(distance<2.5*sq(player[k].scale*5)&&
+ player[k].crouchkeydown&&
+ animation[player[i].targetanimation].height!=lowheight)
+ player[k].targetanimation=sweepanim;
+ //winduppunch
+ else if(distance<1.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight&&
+ !player[k].forwardkeydown&&
+ !player[k].leftkeydown&&
+ !player[k].rightkeydown&&
+ !player[k].crouchkeydown&&
+ !attackweapon&&
+ !reversaltrain)
+ player[k].targetanimation=winduppunchanim;
+ //upunch
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight&&
+ !player[k].forwardkeydown&&
+ !player[k].leftkeydown&&
+ !player[k].rightkeydown&&
+ !player[k].crouchkeydown&&
+ !attackweapon)
+ player[k].targetanimation=upunchanim;
+ //knifefollow
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ player[i].staggerdelay>0&&
+ attackweapon==knife&&
+ player[i].bloodloss>player[i].damagetolerance/2)
+ player[k].targetanimation=knifefollowanim;
+ //knifeslashstart
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight&&
+ !player[k].forwardkeydown&&
+ !player[k].leftkeydown&&
+ !player[k].rightkeydown&&
+ !player[k].crouchkeydown&&
+ attackweapon==knife&&
+ player[k].weaponmissdelay<=0)
+ player[k].targetanimation=knifeslashstartanim;
+ //swordslash
+ else if(distance<4.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight&&
+ !player[k].crouchkeydown&&
+ attackweapon==sword&&
+ player[k].weaponmissdelay<=0)
+ player[k].targetanimation=swordslashanim;
+ //staffhit
+ else if(distance<4.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight&&
+ !player[k].crouchkeydown&&
+ attackweapon==staff&&
+ player[k].weaponmissdelay<=0&&
+ !player[k].leftkeydown&&
+ !player[k].rightkeydown&&
+ !player[k].forwardkeydown)
+ player[k].targetanimation=staffhitanim;
+ //staffspinhit
+ else if(distance<4.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight&&
+ !player[k].crouchkeydown&&
+ attackweapon==staff&&
+ player[k].weaponmissdelay<=0)
+ player[k].targetanimation=staffspinhitanim;
+ //spinkick
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height!=lowheight)
+ player[k].targetanimation=spinkickanim;
+ //lowkick
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height==lowheight&&
+ animation[player[k].targetanimation].attack!=normalattack)
+ player[k].targetanimation=lowkickanim;
+ } else { //AI player
+ if(distance<4.5*sq(player[k].scale*5)){
+ randattack=abs(Random()%5);
+ if(!attackweapon&&distance<2.5*sq(player[k].scale*5)){
+ //sweep
+ if(randattack==0&&animation[player[i].targetanimation].height!=lowheight)
+ player[k].targetanimation=sweepanim;
+ //upunch
+ else if(randattack==1&&animation[player[i].targetanimation].height!=lowheight&&
+ !attackweapon)
+ player[k].targetanimation=upunchanim;
+ //spinkick
+ else if(randattack==2&&animation[player[i].targetanimation].height!=lowheight)
+ player[k].targetanimation=spinkickanim;
+ //lowkick
+ else if(animation[player[i].targetanimation].height==lowheight)
+ player[k].targetanimation=lowkickanim;
+ }
+ if(attackweapon){
+ //sweep
+ if((tutoriallevel!=1||!attackweapon)&&
+ distance<2.5*sq(player[k].scale*5)&&
+ randattack==0&&
+ animation[player[i].targetanimation].height!=lowheight)
+ player[k].targetanimation=sweepanim;
+ //knifeslashstart
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ attackweapon==knife&&
+ player[k].weaponmissdelay<=0)
+ player[k].targetanimation=knifeslashstartanim;
+ //swordslash
+ else if(!(player[0].victim==&player[i]&&
+ player[0].hasvictim&&
+ player[0].targetanimation==swordslashanim)&&
+ attackweapon==sword&&
+ player[k].weaponmissdelay<=0)
+ player[k].targetanimation=swordslashanim;
+ //staffhit
+ else if(!(player[0].victim==&player[i]&&
+ player[0].hasvictim&&
+ player[0].targetanimation==swordslashanim)&&
+ attackweapon==staff&&
+ player[k].weaponmissdelay<=0&&
+ randattack<3)
+ player[k].targetanimation=staffhitanim;
+ //staffspinhit
+ else if(!(player[0].victim==&player[i]&&
+ player[0].hasvictim&&
+ player[0].targetanimation==swordslashanim)&&
+ attackweapon==staff&&
+ player[k].weaponmissdelay<=0&&
+ randattack>=3)
+ player[k].targetanimation=staffspinhitanim;
+ //spinkick
+ else if((tutoriallevel!=1||!attackweapon)&&
+ distance<2.5*sq(player[k].scale*5)&&
+ randattack==1&&
+ animation[player[i].targetanimation].height!=lowheight)
+ player[k].targetanimation=spinkickanim;
+ //lowkick
+ else if(distance<2.5*sq(player[k].scale*5)&&
+ animation[player[i].targetanimation].height==lowheight&&
+ animation[player[k].targetanimation].attack!=normalattack)
+ player[k].targetanimation=lowkickanim;
+ }
+ }
+ }
+ //upunch becomes wolfslap
+ if(player[k].targetanimation==upunchanim&&player[k].creature==wolftype)
+ player[k].targetanimation=wolfslapanim;
+ }
+ //sneak attacks
+ if((k==0)&&(tutoriallevel!=1||tutorialstage==22)&&
+ player[i].howactive<typedead1&&
+ distance<1.5*sq(player[k].scale*5)&&
+ !player[i].skeleton.free&&
+ player[i].targetanimation!=getupfrombackanim&&
+ player[i].targetanimation!=getupfromfrontanim&&
+ (player[i].stunned>0&&player[k].madskills||
+ player[i].surprised>0||
+ player[i].aitype==passivetype||
+ attackweapon&&player[i].stunned>0)&&
+ normaldotproduct(player[i].facing,player[i].coords-player[k].coords)>0){
+ //sneakattack
+ if(!attackweapon){
+ player[k].currentanimation=sneakattackanim;
+ player[k].targetanimation=sneakattackanim;
+ player[i].currentanimation=sneakattackedanim;
+ player[i].targetanimation=sneakattackedanim;
+ player[k].oldcoords=player[k].coords;
+ player[k].coords=player[i].coords;
+ }
+ //knifesneakattack
+ if(attackweapon==knife){
+ player[k].currentanimation=knifesneakattackanim;
+ player[k].targetanimation=knifesneakattackanim;
+ player[i].currentanimation=knifesneakattackedanim;
+ player[i].targetanimation=knifesneakattackedanim;
+ player[i].oldcoords=player[i].coords;
+ player[i].coords=player[k].coords;
+ }
+ //swordsneakattack
+ if(attackweapon==sword){
+ player[k].currentanimation=swordsneakattackanim;
+ player[k].targetanimation=swordsneakattackanim;
+ player[i].currentanimation=swordsneakattackedanim;
+ player[i].targetanimation=swordsneakattackedanim;
+ player[i].oldcoords=player[i].coords;
+ player[i].coords=player[k].coords;
+ }
+ if(attackweapon!=staff){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ player[i].targettilt2=0;
+ player[i].targetframe=1;
+ player[i].currentframe=0;
+ player[i].target=0;
+ player[i].velocity=0;
+ player[k].targettilt2=player[i].targettilt2;
+ player[k].currentframe=player[i].currentframe;
+ player[k].targetframe=player[i].targetframe;
+ player[k].target=player[i].target;
+ player[k].velocity=0;
+ player[k].targetrotation=player[i].rotation;
+ player[k].rotation=player[i].rotation;
+ player[i].targetrotation=player[i].rotation;
+ }
+ }
+ if(animation[player[k].targetanimation].attack==normalattack&&
+ player[k].victim==&player[i]&&
+ (!player[i].skeleton.free)){
+ oldattackkey=1;
+ player[k].targetframe=0;
+ player[k].target=0;
+
+ player[k].targetrotation=roughDirectionTo(player[k].coords,player[i].coords);
+ player[k].targettilt2=pitchTo(player[k].coords,player[i].coords);
+ player[k].lastattack3=player[k].lastattack2;
+ player[k].lastattack2=player[k].lastattack;
+ player[k].lastattack=player[k].targetanimation;
+ }
+ if(player[k].targetanimation==knifefollowanim&&
+ player[k].victim==&player[i]){
+ oldattackkey=1;
+ player[k].targetrotation=roughDirectionTo(player[k].coords,player[i].coords);
+ player[k].targettilt2=pitchTo(player[k].coords,player[i].coords);
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ player[i].targetanimation=knifefollowedanim;
+ player[i].currentanimation=knifefollowedanim;
+ player[i].targettilt2=0;
+ player[i].targettilt2=player[k].targettilt2;
+ player[i].targetframe=1;
+ player[i].currentframe=0;
+ player[i].target=0;
+ player[i].velocity=0;
+ player[k].currentanimation=knifefollowanim;
+ player[k].targetanimation=knifefollowanim;
+ player[k].targettilt2=player[i].targettilt2;
+ player[k].currentframe=player[i].currentframe;
+ player[k].targetframe=player[i].targetframe;
+ player[k].target=player[i].target;
+ player[k].velocity=0;
+ player[k].oldcoords=player[k].coords;
+ player[i].coords=player[k].coords;
+ player[i].targetrotation=player[k].targetrotation;
+ player[i].rotation=player[k].targetrotation;
+ player[k].rotation=player[k].targetrotation;
+ player[i].rotation=player[k].targetrotation;
+ }
+ }
+ }
+ const bool hasstaff=attackweapon==staff;
+ if(k==0&&numplayers>1)
+ for(int i=0;i<numplayers;i++){
+ if(i==k)continue;
+ if((playerrealattackkeydown||player[i].dead||!hasstaff)&&
+ animation[player[k].targetanimation].attack==neutral){
+ const float distance=findDistancefast(&player[k].coords,&player[i].coords);
+ if(!player[i].dead||!realthreat||(!attackweapon&&player[k].crouchkeydown))
+ if(player[i].skeleton.free)
+ if(distance<3.5*sq(player[k].scale*5)&&
+ (player[i].dead||
+ player[i].skeleton.longdead>1000||
+ player[k].isRun()||
+ hasstaff||
+ (attackweapon&&
+ (player[i].skeleton.longdead>2000||
+ player[i].damage>player[i].damagetolerance/8||
+ player[i].bloodloss>player[i].damagetolerance/2)&&
+ distance<1.5*sq(player[k].scale*5)))){
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ if(attackweapon&&tutoriallevel!=1){
+ //crouchstab
+ if(player[k].crouchkeydown&&attackweapon==knife&&distance<1.5*sq(player[k].scale*5))
+ player[k].targetanimation=crouchstabanim;
+ //swordgroundstab
+ if(player[k].crouchkeydown&&distance<1.5*sq(player[k].scale*5)&&attackweapon==sword)
+ player[k].targetanimation=swordgroundstabanim;
+ //staffgroundsmash
+ if(distance<3.5*sq(player[k].scale*5)&&attackweapon==staff)
+ player[k].targetanimation=staffgroundsmashanim;
+ }
+ if(distance<2.5&&
+ player[k].crouchkeydown&&
+ player[k].targetanimation!=crouchstabanim&&
+ !attackweapon&&
+ player[i].dead&&
+ player[i].skeleton.free&&
+ player[i].skeleton.longdead>1000){
+ player[k].targetanimation=killanim;
+ //TODO: refactor this out, what does it do?
+ for(int j=0;j<terrain.numdecals;j++){
+ if((terrain.decaltype[j]==blooddecal||terrain.decaltype[j]==blooddecalslow)&&
+ terrain.decalalivetime[j]<2)
+ terrain.DeleteDecal(j);
+ }
+ for(int l=0;l<objects.numobjects;l++){
+ if(objects.model[l].type==decalstype)
+ for(int j=0;j<objects.model[l].numdecals;j++){
+ if((objects.model[l].decaltype[j]==blooddecal||
+ objects.model[l].decaltype[j]==blooddecalslow)&&
+ objects.model[l].decalalivetime[j]<2)
+ objects.model[l].DeleteDecal(j);
+ }
+ }
+ }
+ if(!player[i].dead||musictype!=2)
+ if(distance<3.5&&
+ (player[k].isRun()||player[k].isIdle()&&player[k].attackkeydown)&&
+ player[k].staggerdelay<=0&&
+ (player[i].dead||
+ player[i].skeleton.longdead<300&&
+ player[k].lastattack!=spinkickanim&&
+ player[i].skeleton.free)&&
+ (!player[i].dead||musictype!=stream_music2)){
+ player[k].targetanimation=dropkickanim;
+ for(int j=0;j<terrain.numdecals;j++){
+ if((terrain.decaltype[j]==blooddecal||terrain.decaltype[j]==blooddecalslow)&&
+ terrain.decalalivetime[j]<2){
+ terrain.DeleteDecal(j);
+ }
+ }
+ for(int l=0;l<objects.numobjects;l++){
+ if(objects.model[l].type==decalstype)
+ for(int j=0;j<objects.model[l].numdecals;j++){
+ if((objects.model[l].decaltype[j]==blooddecal||
+ objects.model[l].decaltype[j]==blooddecalslow)&&
+ objects.model[l].decalalivetime[j]<2){
+ objects.model[l].DeleteDecal(j);
+ }
+ }
+ }
+ }
+ }
+ if(animation[player[k].targetanimation].attack==normalattack&&
+ player[k].victim==&player[i]&&
+ (!player[i].skeleton.free||
+ player[k].targetanimation==killanim||
+ player[k].targetanimation==crouchstabanim||
+ player[k].targetanimation==swordgroundstabanim||
+ player[k].targetanimation==staffgroundsmashanim||
+ player[k].targetanimation==dropkickanim)){
+ oldattackkey=1;
+ player[k].targetframe=0;
+ player[k].target=0;
+
+ XYZ targetpoint=player[i].coords;
+ if(player[k].targetanimation==crouchstabanim||
+ player[k].targetanimation==swordgroundstabanim||
+ player[k].targetanimation==staffgroundsmashanim){
+ targetpoint+=(playerJoint(i,abdomen).position+
+ playerJoint(i,neck).position)/2*
+ player[i].scale;
+ }
+ player[k].targetrotation=roughDirectionTo(player[k].coords,targetpoint);
+ player[k].targettilt2=pitchTo(player[k].coords,targetpoint);
+
+ if(player[k].targetanimation==crouchstabanim||player[k].targetanimation==swordgroundstabanim){
+ player[k].targetrotation+=(float)(abs(Random()%100)-50)/4;
+ }
+
+ if(player[k].targetanimation==staffgroundsmashanim)
+ player[k].targettilt2+=10;
+
+ player[k].lastattack3=player[k].lastattack2;
+ player[k].lastattack2=player[k].lastattack;
+ player[k].lastattack=player[k].targetanimation;
+
+ if(player[k].targetanimation==swordgroundstabanim){
+ player[k].targetrotation+=30;
+ }
+ }
+ }
+ }
+ if(!player[k].hasvictim){
+ //find victim
+ for(int i=0;i<numplayers;i++){
+ if(i==k||!(i==0||k==0))continue;
+ if(!player[i].skeleton.free){
+ if(player[k].hasvictim){
+ if(findDistancefast(&player[k].coords,&player[i].coords)<
+ findDistancefast(&player[k].coords,&player[k].victim->coords))
+ player[k].victim=&player[i];
+ }else{
+ player[k].victim=&player[i];
+ player[k].hasvictim=1;
+ }
+ }
+ }
+ }
+ if(player[k].aitype==playercontrolled)
+ //rabbit kick
+ if(player[k].attackkeydown&&
+ player[k].isRun()&&
+ player[k].wasRun()&&
+ ((player[k].hasvictim&&
+ findDistancefast(&player[k].coords,&player[k].victim->coords)<12*sq(player[k].scale*5)&&
+ findDistancefast(&player[k].coords,&player[k].victim->coords)>7*sq(player[k].scale*5)&&
+ !player[k].victim->skeleton.free&&
+ player[k].victim->targetanimation!=getupfrombackanim&&
+ player[k].victim->targetanimation!=getupfromfrontanim&&
+ animation[player[k].victim->targetanimation].height!=lowheight&&
+ player[k].aitype!=playercontrolled&& //wat???
+ normaldotproduct(player[k].facing,player[k].victim->coords-player[k].coords)>0&&
+ player[k].rabbitkickenabled)||
+ player[k].jumpkeydown)){
+ oldattackkey=1;
+ setAnimation(k,rabbitkickanim);
+ }
+ //update counts
+ if(animation[player[k].targetanimation].attack&&k==0){
+ numattacks++;
+ switch(attackweapon){
+ case 0: numunarmedattack++; break;
+ case knife: numknifeattack++; break;
+ case sword: numswordattack++; break;
+ case staff: numstaffattack++; break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Game::doPlayerCollisions(){
+ static XYZ rotatetarget;
+ static float collisionradius;
+ if(numplayers>1)
+ for(int k=0;k<numplayers;k++)
+ for(int i=k+1;i<numplayers;i++){
+ //neither player is part of a reversal
+ if((animation[player[i].targetanimation].attack!=reversed&&
+ animation[player[i].targetanimation].attack!=reversal&&
+ animation[player[k].targetanimation].attack!=reversed&&
+ animation[player[k].targetanimation].attack!=reversal)||(i!=0&&k!=0))
+ if((animation[player[i].currentanimation].attack!=reversed&&
+ animation[player[i].currentanimation].attack!=reversal&&
+ animation[player[k].currentanimation].attack!=reversed&&
+ animation[player[k].currentanimation].attack!=reversal)||(i!=0&&k!=0))
+ //neither is sleeping
+ if(player[i].howactive<=typesleeping&&player[k].howactive<=typesleeping)
+ if(player[i].howactive!=typesittingwall&&player[k].howactive!=typesittingwall)
+ //in same patch, neither is climbing
+ if(player[i].whichpatchx==player[k].whichpatchx&&
+ player[i].whichpatchz==player[k].whichpatchz&&
+ player[k].skeleton.oldfree==player[k].skeleton.free&&
+ player[i].skeleton.oldfree==player[i].skeleton.free&&
+ player[i].targetanimation!=climbanim&&
+ player[i].targetanimation!=hanganim&&
+ player[k].targetanimation!=climbanim&&
+ player[k].targetanimation!=hanganim)
+ //players are close (bounding box test)
+ if(player[i].coords.y>player[k].coords.y-3)
+ if(player[i].coords.y<player[k].coords.y+3)
+ if(player[i].coords.x>player[k].coords.x-3)
+ if(player[i].coords.x<player[k].coords.x+3)
+ if(player[i].coords.z>player[k].coords.z-3)
+ if(player[i].coords.z<player[k].coords.z+3){
+ //spread fire from player to player
+ if(findDistancefast(&player[i].coords,&player[k].coords)
+ <3*sq((player[i].scale+player[k].scale)*2.5)){
+ if(player[i].onfire||player[k].onfire){
+ if(!player[i].onfire)player[i].CatchFire();
+ if(!player[k].onfire)player[k].CatchFire();
+ }
+ }
+
+ XYZ tempcoords1=player[i].coords;
+ XYZ tempcoords2=player[k].coords;
+ if(!player[i].skeleton.oldfree)
+ tempcoords1.y+=playerJoint(i,abdomen).position.y*player[i].scale;
+ if(!player[k].skeleton.oldfree)
+ tempcoords2.y+=playerJoint(k,abdomen).position.y*player[k].scale;
+ collisionradius=1.2*sq((player[i].scale+player[k].scale)*2.5);
+ if(player[0].hasvictim)
+ if(player[0].targetanimation==rabbitkickanim&&(k==0||i==0)&&!player[0].victim->skeleton.free)
+ collisionradius=3;
+ if((!player[i].skeleton.oldfree||!player[k].skeleton.oldfree)&&
+ (findDistancefast(&tempcoords1,&tempcoords2)<collisionradius||
+ findDistancefast(&player[i].coords,&player[k].coords)<collisionradius)){
+ //jump down on a dead body
+ if(k==0||i==0){
+ int l=i?i:k;
+ if(player[0].targetanimation==jumpdownanim&&
+ !player[0].skeleton.oldfree&&
+ !player[0].skeleton.free&&
+ player[l].skeleton.oldfree&&
+ player[l].skeleton.free&&
+ player[l].dead&&
+ player[0].lastcollide<=0&&
+ fabs(player[l].coords.y-player[0].coords.y)<.2&&
+ findDistancefast(&player[0].coords,&player[l].coords)<.7*sq((player[l].scale+player[0].scale)*2.5)){
+ player[0].coords.y=player[l].coords.y;
+ player[l].velocity=player[0].velocity;
+ player[l].skeleton.free=0;
+ player[l].rotation=0;
+ player[l].RagDoll(0);
+ player[l].DoDamage(20);
+ camerashake+=.3;
+ player[l].skeleton.longdead=0;
+ player[0].lastcollide=1;
+ }
+ }
+
+ if( (player[i].skeleton.oldfree==1&&findLengthfast(&player[i].velocity)>1)||
+ (player[k].skeleton.oldfree==1&&findLengthfast(&player[k].velocity)>1)||
+ (player[i].skeleton.oldfree==0&&player[k].skeleton.oldfree==0)){
+ rotatetarget=player[k].velocity-player[i].velocity;
+ if((player[i].targetanimation!=getupfrombackanim&&player[i].targetanimation!=getupfromfrontanim||
+ player[i].skeleton.free)&&
+ (player[k].targetanimation!=getupfrombackanim&&player[k].targetanimation!=getupfromfrontanim||
+ player[k].skeleton.free))
+ if((((k!=0&&findLengthfast(&rotatetarget)>150||
+ k==0&&findLengthfast(&rotatetarget)>50&&player[0].rabbitkickragdoll)&&
+ normaldotproduct(rotatetarget,player[k].coords-player[i].coords)>0)&&
+ (k==0||
+ k!=0&&player[i].skeleton.oldfree==1&&animation[player[k].currentanimation].attack==neutral||
+ /*i!=0&&*/player[k].skeleton.oldfree==1&&animation[player[i].currentanimation].attack==neutral))||
+ (player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim||player[i].isFlip())&&
+ (player[k].targetanimation==jumpupanim||player[k].targetanimation==jumpdownanim||player[k].isFlip())&&
+ k==0&&!player[i].skeleton.oldfree&&!player[k].skeleton.oldfree){
+ //If hit by body
+ if( (i!=0||player[i].skeleton.free)&&
+ (k!=0||player[k].skeleton.free)||
+ (animation[player[i].targetanimation].height==highheight&&
+ animation[player[k].targetanimation].height==highheight)){
+ if(tutoriallevel!=1){
+ emit_sound_at(heavyimpactsound, player[i].coords);
+ }
+
+ player[i].RagDoll(0);
+ if(player[i].damage>player[i].damagetolerance-findLengthfast(&rotatetarget)/4&&!player[i].dead){
+ award_bonus(0, aimbonus);
+ }
+ player[i].DoDamage(findLengthfast(&rotatetarget)/4);
+ player[k].RagDoll(0);
+ if(player[k].damage>player[k].damagetolerance-findLengthfast(&rotatetarget)/4&&!player[k].dead){
+ award_bonus(0, aimbonus); // Huh, again?
+ }
+ player[k].DoDamage(findLengthfast(&rotatetarget)/4);
+
+ for(int j=0;j<player[i].skeleton.num_joints;j++){
+ player[i].skeleton.joints[j].velocity=player[i].skeleton.joints[j].velocity/5+player[k].velocity;
+ }
+ for(int j=0;j<player[k].skeleton.num_joints;j++){
+ player[k].skeleton.joints[j].velocity=player[k].skeleton.joints[j].velocity/5+player[i].velocity;
+ }
+
+ }
+ }
+ if( (animation[player[i].targetanimation].attack==neutral||
+ animation[player[i].targetanimation].attack==normalattack)&&
+ (animation[player[k].targetanimation].attack==neutral||
+ animation[player[k].targetanimation].attack==normalattack)){
+ //If bumped
+ if(player[i].skeleton.oldfree==0&&player[k].skeleton.oldfree==0){
+ if(findDistancefast(&player[k].coords,&player[i].coords)<.5*sq((player[i].scale+player[k].scale)*2.5)){
+ rotatetarget=player[k].coords-player[i].coords;
+ Normalise(&rotatetarget);
+ player[k].coords=(player[k].coords+player[i].coords)/2;
+ player[i].coords=player[k].coords-rotatetarget*fast_sqrt(.6)/2
+ *sq((player[i].scale+player[k].scale)*2.5);
+ player[k].coords+=rotatetarget*fast_sqrt(.6)/2*sq((player[i].scale+player[k].scale)*2.5);
+ if(player[k].howactive==typeactive||hostile)
+ if(player[k].isIdle()){
+ if(player[k].howactive<typesleeping)
+ setAnimation(k,player[k].getStop());
+ else if(player[k].howactive==typesleeping)
+ setAnimation(k,getupfromfrontanim);
+ if(!editorenabled)
+ player[k].howactive=typeactive;
+ }
+ if(player[i].howactive==typeactive||hostile)
+ if(player[i].isIdle()){
+ if(player[i].howactive<typesleeping)
+ setAnimation(i,player[k].getStop());
+ else
+ setAnimation(i,getupfromfrontanim);
+ if(!editorenabled)
+ player[i].howactive=typeactive;
+ }
+ }
+ //jump down on player
+ if(hostile){
+ if(k==0&&i!=0&&player[k].targetanimation==jumpdownanim&&
+ !player[i].isCrouch()&&
+ player[i].targetanimation!=rollanim&&
+ !player[k].skeleton.oldfree&&!
+ player[k].skeleton.free&&
+ player[k].lastcollide<=0&&
+ player[k].velocity.y<-10){
+ player[i].velocity=player[k].velocity;
+ player[k].velocity=player[k].velocity*-.5;
+ player[k].velocity.y=player[i].velocity.y;
+ player[i].DoDamage(20);
+ player[i].RagDoll(0);
+ player[k].lastcollide=1;
+ award_bonus(k, AboveBonus);
+ }
+ if(i==0&&k!=0&&player[i].targetanimation==jumpdownanim&&
+ !player[k].isCrouch()&&
+ player[k].targetanimation!=rollanim&&
+ !player[i].skeleton.oldfree&&
+ !player[i].skeleton.free&&
+ player[i].lastcollide<=0&&
+ player[i].velocity.y<-10){
+ player[k].velocity=player[i].velocity;
+ player[i].velocity=player[i].velocity*-.3;
+ player[i].velocity.y=player[k].velocity.y;
+ player[k].DoDamage(20);
+ player[k].RagDoll(0);
+ player[i].lastcollide=1;
+ award_bonus(i, AboveBonus);
+ }
+ }
+ }
+ }
+ }
+ player[i].CheckKick();
+ player[k].CheckKick();
+ }
+ }
+ }
+}