+ 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();
+ }
+ }
+ }
+}
+
+
+
+void Game::doAI(int i){
+ static bool connected;
+ if(player[i].aitype!=playercontrolled&&indialogue==-1){
+ player[i].jumpclimb=0;
+ //disable movement in editor
+ if(editorenabled)
+ player[i].stunned=1;
+
+ player[i].pause=0;
+ if(findDistancefastflat(&player[0].coords,&player[i].coords)<30&&
+ player[0].coords.y>player[i].coords.y+2&&
+ !player[0].onterrain)
+ player[i].pause=1;
+
+ //pathfinding
+ if(player[i].aitype==pathfindtype){
+ if(player[i].finalpathfindpoint==-1){
+ float closestdistance;
+ float tempdist;
+ int closest;
+ XYZ colpoint;
+ closest=-1;
+ closestdistance=-1;
+ for(int j=0;j<numpathpoints;j++)
+ if(closest==-1||findDistancefast(&player[i].finalfinaltarget,&pathpoint[j])<closestdistance){
+ closestdistance=findDistancefast(&player[i].finalfinaltarget,&pathpoint[j]);
+ closest=j;
+ player[i].finaltarget=pathpoint[j];
+ }
+ player[i].finalpathfindpoint=closest;
+ for(int j=0;j<numpathpoints;j++)
+ for(int k=0;k<numpathpointconnect[j];k++){
+ DistancePointLine(&player[i].finalfinaltarget, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist,&colpoint );
+ if(sq(tempdist)<closestdistance)
+ if(findDistance(&colpoint,&pathpoint[j])+findDistance(&colpoint,&pathpoint[pathpointconnect[j][k]])<
+ findDistance(&pathpoint[j],&pathpoint[pathpointconnect[j][k]])+.1){
+ closestdistance=sq(tempdist);
+ closest=j;
+ player[i].finaltarget=colpoint;
+ }
+ }
+ player[i].finalpathfindpoint=closest;
+
+ }
+ if(player[i].targetpathfindpoint==-1){
+ float closestdistance;
+ float tempdist;
+ int closest;
+ XYZ colpoint;
+ closest=-1;
+ closestdistance=-1;
+ if(player[i].lastpathfindpoint==-1){
+ for(int j=0;j<numpathpoints;j++){
+ if(j!=player[i].lastpathfindpoint)
+ if(closest==-1||(findDistancefast(&player[i].coords,&pathpoint[j])<closestdistance)){
+ closestdistance=findDistancefast(&player[i].coords,&pathpoint[j]);
+ closest=j;
+ }
+ }
+ player[i].targetpathfindpoint=closest;
+ for(int j=0;j<numpathpoints;j++)
+ if(j!=player[i].lastpathfindpoint)
+ for(int k=0;k<numpathpointconnect[j];k++){
+ DistancePointLine(&player[i].coords, &pathpoint[j], &pathpoint[pathpointconnect[j][k]], &tempdist,&colpoint );
+ if(sq(tempdist)<closestdistance){
+ if(findDistance(&colpoint,&pathpoint[j])+findDistance(&colpoint,&pathpoint[pathpointconnect[j][k]])<
+ findDistance(&pathpoint[j],&pathpoint[pathpointconnect[j][k]])+.1){
+ closestdistance=sq(tempdist);
+ closest=j;
+ }
+ }
+ }
+ player[i].targetpathfindpoint=closest;
+ }
+ else
+ {
+ for(int j=0;j<numpathpoints;j++)
+ if(j!=player[i].lastpathfindpoint&&
+ j!=player[i].lastpathfindpoint2&&
+ j!=player[i].lastpathfindpoint3&&
+ j!=player[i].lastpathfindpoint4){
+ connected=0;
+ if(numpathpointconnect[j])
+ for(int k=0;k<numpathpointconnect[j];k++)
+ if(pathpointconnect[j][k]==player[i].lastpathfindpoint)
+ connected=1;
+ if(!connected)
+ if(numpathpointconnect[player[i].lastpathfindpoint])
+ for(int k=0;k<numpathpointconnect[player[i].lastpathfindpoint];k++)
+ if(pathpointconnect[player[i].lastpathfindpoint][k]==j)
+ connected=1;
+ if(connected){
+ tempdist=findPathDist(j,player[i].finalpathfindpoint);
+ if(closest==-1||tempdist<closestdistance){
+ closestdistance=tempdist;
+ closest=j;
+ }
+ }
+ }
+ player[i].targetpathfindpoint=closest;
+ }
+ }
+ player[i].losupdatedelay-=multiplier;
+
+ player[i].targetrotation=roughDirectionTo(player[i].coords,pathpoint[player[i].targetpathfindpoint]);
+ player[i].lookrotation=player[i].targetrotation;
+
+ //reached target point
+ if(findDistancefastflat(&player[i].coords,&pathpoint[player[i].targetpathfindpoint])<.6){
+ player[i].lastpathfindpoint4=player[i].lastpathfindpoint3;
+ player[i].lastpathfindpoint3=player[i].lastpathfindpoint2;
+ player[i].lastpathfindpoint2=player[i].lastpathfindpoint;
+ player[i].lastpathfindpoint=player[i].targetpathfindpoint;
+ if(player[i].lastpathfindpoint2==-1)
+ player[i].lastpathfindpoint2=player[i].lastpathfindpoint;
+ if(player[i].lastpathfindpoint3==-1)
+ player[i].lastpathfindpoint3=player[i].lastpathfindpoint2;
+ if(player[i].lastpathfindpoint4==-1)
+ player[i].lastpathfindpoint4=player[i].lastpathfindpoint3;
+ player[i].targetpathfindpoint=-1;
+ }
+ if( findDistancefastflat(&player[i].coords,&player[i].finalfinaltarget)<
+ findDistancefastflat(&player[i].coords,&player[i].finaltarget)||
+ findDistancefastflat(&player[i].coords,&player[i].finaltarget)<.6*sq(player[i].scale*5)||
+ player[i].lastpathfindpoint==player[i].finalpathfindpoint){
+ player[i].aitype=passivetype;
+ }
+
+ player[i].forwardkeydown=1;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8)
+ player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
+ player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))
+ player[i].jumpkeydown=1;
+
+ if((tutoriallevel!=1||cananger)&&
+ hostile&&
+ !player[0].dead&&
+ findDistancefast(&player[i].coords,&player[0].coords)<400&&
+ player[i].occluded<25){
+ if(findDistancefast(&player[i].coords,&player[0].coords)<12&&
+ animation[player[0].targetanimation].height!=lowheight&&
+ !editorenabled&&
+ (player[0].coords.y<player[i].coords.y+5||player[0].onterrain))
+ player[i].aitype=attacktypecutoff;
+ if(findDistancefast(&player[i].coords,&player[0].coords)<30&&
+ animation[player[0].targetanimation].height==highheight&&
+ !editorenabled)
+ player[i].aitype=attacktypecutoff;
+
+ if(player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2){
+ player[i].losupdatedelay=.2;
+ for(int j=0;j<numplayers;j++)
+ if(j==0||player[j].skeleton.free||player[j].aitype!=passivetype)
+ if(abs(Random()%2)||animation[player[j].targetanimation].height!=lowheight||j!=0)
+ if(findDistancefast(&player[i].coords,&player[j].coords)<400)
+ if(normaldotproduct(player[i].facing,player[j].coords-player[i].coords)>0)
+ if(player[j].coords.y<player[i].coords.y+5||player[j].onterrain)
+ if(!player[j].isWallJump()&&-1==checkcollide(
+ DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)
+ *player[i].scale+player[i].coords,
+ DoRotation(playerJoint(j,head).position,0,player[j].rotation,0)
+ *player[j].scale+player[j].coords)||
+ (player[j].targetanimation==hanganim&&
+ normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
+ player[i].aitype=searchtype;
+ player[i].lastchecktime=12;
+ player[i].lastseen=player[j].coords;
+ player[i].lastseentime=12;
+ }
+ }
+ }
+ if(player[i].aitype==attacktypecutoff&&musictype!=2)
+ if(player[i].creature!=wolftype){
+ player[i].stunned=.6;
+ player[i].surprised=.6;
+ }
+ }
+
+ if(player[i].aitype!=passivetype&&leveltime>.5)
+ player[i].howactive=typeactive;
+
+ if(player[i].aitype==passivetype){
+ player[i].aiupdatedelay-=multiplier;
+ player[i].losupdatedelay-=multiplier;
+ player[i].lastseentime+=multiplier;
+ player[i].pausetime-=multiplier;
+ if(player[i].lastseentime>1)
+ player[i].lastseentime=1;
+
+ if(player[i].aiupdatedelay<0){
+ if(player[i].numwaypoints>1&&player[i].howactive==typeactive&&player[i].pausetime<=0){
+ player[i].targetrotation=roughDirectionTo(player[i].coords,player[i].waypoints[player[i].waypoint]);
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+
+ if(findDistancefastflat(&player[i].coords,&player[i].waypoints[player[i].waypoint])<1){
+ if(player[i].waypointtype[player[i].waypoint]==wppause)
+ player[i].pausetime=4;
+ player[i].waypoint++;
+ if(player[i].waypoint>player[i].numwaypoints-1)
+ player[i].waypoint=0;
+
+ }
+ }
+
+ if(player[i].numwaypoints>1&&player[i].howactive==typeactive&&player[i].pausetime<=0)
+ player[i].forwardkeydown=1;
+ else
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)
+ player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)
+ player[i].targetrotation+=90;
+ else
+ player[i].targetrotation-=90;
+ }
+ }
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
+ player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))
+ player[i].jumpkeydown=1;
+
+
+ //hearing sounds
+ if(!editorenabled){
+ if(player[i].howactive<=typesleeping)
+ if(numenvsounds>0&&(tutoriallevel!=1||cananger)&&hostile)
+ for(int j=0;j<numenvsounds;j++){
+ float vol=player[i].howactive==typesleeping?envsoundvol[j]-14:envsoundvol[j];
+ if(vol>0&&findDistancefast(&player[i].coords,&envsound[j])<
+ 2*(vol+vol*(player[i].creature==rabbittype)*3))
+ player[i].aitype=attacktypecutoff;
+ }
+
+ if(player[i].aitype!=passivetype){
+ if(player[i].howactive==typesleeping)
+ setAnimation(i,getupfromfrontanim);
+ player[i].howactive=typeactive;
+ }
+ }
+
+ if(player[i].howactive<typesleeping&&
+ ((tutoriallevel!=1||cananger)&&hostile)&&
+ !player[0].dead&&
+ findDistancefast(&player[i].coords,&player[0].coords)<400&&
+ player[i].occluded<25){
+ if(findDistancefast(&player[i].coords,&player[0].coords)<12&&
+ animation[player[0].targetanimation].height!=lowheight&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+ if(findDistancefast(&player[i].coords,&player[0].coords)<30&&
+ animation[player[0].targetanimation].height==highheight&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+
+ //wolf smell
+ if(player[i].creature==wolftype){
+ XYZ windsmell;
+ for(int j=0;j<numplayers;j++){
+ if(j==0||(player[j].dead&&player[j].bloodloss>0)){
+ float smelldistance=50;
+ if(j==0&&player[j].num_weapons>0){
+ if(weapons.bloody[player[j].weaponids[0]])
+ smelldistance=100;
+ if(player[j].num_weapons==2)
+ if(weapons.bloody[player[j].weaponids[1]])
+ smelldistance=100;
+ }
+ if(j!=0)
+ smelldistance=100;
+ windsmell=windvector;
+ Normalise(&windsmell);
+ windsmell=windsmell*2+player[j].coords;
+ if(findDistancefast(&player[i].coords,&windsmell)<smelldistance&&!editorenabled)
+ player[i].aitype=attacktypecutoff;
+ }
+ }
+ }
+
+ if(player[i].howactive<typesleeping&&player[i].losupdatedelay<0&&!editorenabled&&player[i].occluded<2){
+ player[i].losupdatedelay=.2;
+ for(int j=0;j<numplayers;j++){
+ if(j==0||player[j].skeleton.free||player[j].aitype!=passivetype){
+ if(abs(Random()%2)||animation[player[j].targetanimation].height!=lowheight||j!=0)
+ if(findDistancefast(&player[i].coords,&player[j].coords)<400)
+ if(normaldotproduct(player[i].facing,player[j].coords-player[i].coords)>0)
+ if((-1==checkcollide(
+ DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)*
+ player[i].scale+player[i].coords,
+ DoRotation(playerJoint(j,head).position,0,player[j].rotation,0)*
+ player[j].scale+player[j].coords)&&
+ !player[j].isWallJump())||
+ (player[j].targetanimation==hanganim&&
+ normaldotproduct(player[j].facing,player[i].coords-player[j].coords)<0)){
+ player[i].lastseentime-=.2;
+ if(j==0&&animation[player[j].targetanimation].height==lowheight)
+ player[i].lastseentime-=.4;
+ else
+ player[i].lastseentime-=.6;
+ }
+ if(player[i].lastseentime<=0){
+ player[i].aitype=searchtype;
+ player[i].lastchecktime=12;
+ player[i].lastseen=player[j].coords;
+ player[i].lastseentime=12;
+ }
+ }
+ }
+ }
+ }
+ //alerted surprise
+ if(player[i].aitype==attacktypecutoff&&musictype!=2){
+ if(player[i].creature!=wolftype){
+ player[i].stunned=.6;
+ player[i].surprised=.6;
+ }
+ if(player[i].creature==wolftype){
+ player[i].stunned=.47;
+ player[i].surprised=.47;
+ }
+ numseen++;
+ }
+ }
+
+ //search for player
+ int j;
+ if(player[i].aitype==searchtype){
+ player[i].aiupdatedelay-=multiplier;
+ player[i].losupdatedelay-=multiplier;
+ if(!player[i].pause)
+ player[i].lastseentime-=multiplier;
+ player[i].lastchecktime-=multiplier;
+
+ if(player[i].isRun()&&!player[i].onground){
+ if(player[i].coords.y>terrain.getHeight(player[i].coords.x,player[i].coords.z)+10){
+ XYZ test2=player[i].coords+player[i].facing;
+ test2.y+=5;
+ XYZ test=player[i].coords+player[i].facing;
+ test.y-=10;
+ j=checkcollide(test2,test,player[i].laststanding);
+ if(j==-1)
+ j=checkcollide(test2,test);
+ if(j==-1){
+ player[i].velocity=0;
+ setAnimation(i,player[i].getStop());
+ player[i].targetrotation+=180;
+ player[i].stunned=.5;
+ //player[i].aitype=passivetype;
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ else player[i].laststanding=j;
+ }
+ }
+ //check out last seen location
+ if(player[i].aiupdatedelay<0){
+ player[i].targetrotation=roughDirectionTo(player[i].coords,player[i].lastseen);
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+ player[i].forwardkeydown=1;
+
+ if(findDistancefastflat(&player[i].coords,&player[i].lastseen)<1*sq(player[i].scale*5)||player[i].lastchecktime<0){
+ player[i].forwardkeydown=0;
+ player[i].aiupdatedelay=1;
+ player[i].lastseen.x+=(float(Random()%100)-50)/25;
+ player[i].lastseen.z+=(float(Random()%100)-50)/25;
+ player[i].lastchecktime=3;
+ }
+
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)player[i].targetrotation+=90;
+ else player[i].targetrotation-=90;
+ }
+ }
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
+ player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))
+ player[i].jumpkeydown=1;
+
+ if(numenvsounds>0&&((tutoriallevel!=1||cananger)&&hostile))
+ for(int k=0;k<numenvsounds;k++){
+ if(findDistancefast(&player[i].coords,&envsound[k])<2*(envsoundvol[k]+envsoundvol[k]*(player[i].creature==rabbittype)*3)){
+ player[i].aitype=attacktypecutoff;
+ }
+ }
+
+ if(!player[0].dead&&
+ player[i].losupdatedelay<0&&
+ !editorenabled&&
+ player[i].occluded<2&&
+ ((tutoriallevel!=1||cananger)&&hostile)){
+ player[i].losupdatedelay=.2;
+ if(findDistancefast(&player[i].coords,&player[0].coords)<4&&animation[player[i].targetanimation].height!=lowheight){
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ if(abs(Random()%2)||animation[player[i].targetanimation].height!=lowheight)
+ //TODO: factor out canSeePlayer()
+ if(findDistancefast(&player[i].coords,&player[0].coords)<400)
+ if(normaldotproduct(player[i].facing,player[0].coords-player[i].coords)>0)
+ if((checkcollide(
+ DoRotation(playerJoint(i,head).position,0,player[i].rotation,0)*
+ player[i].scale+player[i].coords,
+ DoRotation(playerJoint(0,head).position,0,player[0].rotation,0)*
+ player[0].scale+player[0].coords)==-1)||
+ (player[0].targetanimation==hanganim&&normaldotproduct(
+ player[0].facing,player[i].coords-player[0].coords)<0)){
+ /* //TODO: changed j to 0 on a whim, make sure this is correct
+ (player[j].targetanimation==hanganim&&normaldotproduct(
+ player[j].facing,player[i].coords-player[j].coords)<0)
+ */
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ }
+ //player escaped
+ if(player[i].lastseentime<0){
+ //player[i].aitype=passivetype;
+ numescaped++;
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ }
+
+ if(player[i].aitype!=gethelptype)
+ player[i].runninghowlong=0;
+
+ //get help from buddies
+ if(player[i].aitype==gethelptype){
+ player[i].runninghowlong+=multiplier;
+ player[i].aiupdatedelay-=multiplier;
+
+ if(player[i].aiupdatedelay<0||player[i].ally==0){
+ player[i].aiupdatedelay=.2;
+
+ //find closest ally
+ //TODO: factor out closest search somehow
+ if(!player[i].ally){
+ int closest=-1;
+ float closestdist=-1;
+ for(int k=0;k<numplayers;k++){
+ if(k!=i&&k!=0&&!player[k].dead&&
+ player[k].howactive<typedead1&&
+ !player[k].skeleton.free&&
+ player[k].aitype==passivetype){
+ float distance=findDistancefast(&player[i].coords,&player[k].coords);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=k;
+ }
+ closest=k;
+ }
+ }
+ if(closest!=-1)
+ player[i].ally=closest;
+ else
+ player[i].ally=0;
+ player[i].lastseen=player[0].coords;
+ player[i].lastseentime=12;
+ }
+
+
+ player[i].lastchecktime=12;
+
+ XYZ facing=player[i].coords;
+ XYZ flatfacing=player[player[i].ally].coords;
+ facing.y+=playerJoint(i,head).position.y*player[i].scale;
+ flatfacing.y+=playerJoint(player[i].ally,head).position.y*player[player[i].ally].scale;
+ if(-1!=checkcollide(facing,flatfacing))
+ player[i].lastseentime-=.1;
+
+ //no available ally, run back to player
+ if(player[i].ally<=0||
+ player[player[i].ally].skeleton.free||
+ player[player[i].ally].aitype!=passivetype||
+ player[i].lastseentime<=0){
+ player[i].aitype=searchtype;
+ player[i].lastseentime=12;
+ }
+
+ //seek out ally
+ if(player[i].ally>0){
+ player[i].targetrotation=roughDirectionTo(player[i].coords,player[player[i].ally].coords);
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+ player[i].forwardkeydown=1;
+
+ if(findDistancefastflat(&player[i].coords,&player[player[i].ally].coords)<3){
+ player[i].aitype=searchtype;
+ player[i].lastseentime=12;
+ player[player[i].ally].aitype=searchtype;
+ if(player[player[i].ally].lastseentime<player[i].lastseentime){
+ player[player[i].ally].lastseen=player[i].lastseen;
+ player[player[i].ally].lastseentime=player[i].lastseentime;
+ player[player[i].ally].lastchecktime=player[i].lastchecktime;
+ }
+ }
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)
+ player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)
+ player[i].targetrotation+=90;
+ else
+ player[i].targetrotation-=90;
+ }
+ }
+ }
+
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].attackkeydown=0;
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
+ player[i].jumpkeydown=0;
+ if(player[i].collided>.8&&player[i].jumppower>=5)
+ player[i].jumpkeydown=1;
+ }
+
+ //retreiving a weapon on the ground
+ if(player[i].aitype==getweapontype){
+ player[i].aiupdatedelay-=multiplier;
+ player[i].lastchecktime-=multiplier;
+
+ if(player[i].aiupdatedelay<0){
+ player[i].aiupdatedelay=.2;
+
+ //ALLY IS WEPON
+ if(player[i].ally<0){
+ int closest=-1;
+ float closestdist=-1;
+ for(int k=0;k<weapons.numweapons;k++)
+ if(weapons.owner[k]==-1){
+ float distance=findDistancefast(&player[i].coords,&weapons.position[k]);
+ if(closestdist==-1||distance<closestdist){
+ closestdist=distance;
+ closest=k;
+ }
+ closest=k;
+ }
+ if(closest!=-1)
+ player[i].ally=closest;
+ else
+ player[i].ally=-1;
+ }
+
+ player[i].lastseentime=12;
+
+ if(!player[0].dead&&((tutoriallevel!=1||cananger)&&hostile))
+ if(player[i].ally<0||player[i].weaponactive!=-1||player[i].lastchecktime<=0){
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ if(!player[0].dead)
+ if(player[i].ally>=0){
+ if(weapons.owner[player[i].ally]!=-1||
+ findDistancefast(&player[i].coords,&weapons.position[player[i].ally])>16){
+ player[i].aitype=attacktypecutoff;
+ player[i].lastseentime=1;
+ }
+ //TODO: factor these out as moveToward()
+ player[i].targetrotation=roughDirectionTo(player[i].coords,weapons.position[player[i].ally]);
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.05;
+ player[i].forwardkeydown=1;
+
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8){
+ if(!player[i].avoidsomething)
+ player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ else{
+ XYZ leftpos,rightpos;
+ float leftdist,rightdist;
+ leftpos = player[i].coords+DoRotation(player[i].facing,0,90,0);
+ rightpos = player[i].coords-DoRotation(player[i].facing,0,90,0);
+ leftdist = findDistancefast(&leftpos, &player[i].avoidwhere);
+ rightdist = findDistancefast(&rightpos, &player[i].avoidwhere);
+ if(leftdist<rightdist)
+ player[i].targetrotation+=90;
+ else
+ player[i].targetrotation-=90;
+ }
+ }
+ }
+
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].throwkeydown=1;
+ player[i].crouchkeydown=0;
+ if(player[i].targetanimation!=crouchremoveknifeanim&&
+ player[i].targetanimation!=removeknifeanim)
+ player[i].throwtogglekeydown=0;
+ player[i].drawkeydown=0;
+ }
+ if(player[i].collided<1||player[i].targetanimation!=jumpupanim)
+ player[i].jumpkeydown=0;
+ if((player[i].collided>.8&&player[i].jumppower>=5))
+ player[i].jumpkeydown=1;
+ }
+
+ if(player[i].aitype==attacktypecutoff){
+ player[i].aiupdatedelay-=multiplier;
+ //dodge or reverse rabbit kicks, knife throws, flips
+ if(player[i].damage<player[i].damagetolerance*2/3)
+ if((player[0].targetanimation==rabbitkickanim||
+ player[0].targetanimation==knifethrowanim||
+ (player[0].isFlip()&&
+ normaldotproduct(player[0].facing,player[0].coords-player[i].coords)<0))&&
+ !player[0].skeleton.free&&
+ (player[i].aiupdatedelay<.1)){
+ player[i].attackkeydown=0;
+ if(player[i].isIdle())
+ player[i].crouchkeydown=1;
+ if(player[0].targetanimation!=rabbitkickanim&&player[0].weaponactive!=-1){
+ if(weapons.type[player[0].weaponids[0]]==knife){
+ if(player[i].isIdle()||player[i].isCrouch()||player[i].isRun()||player[i].isFlip()){
+ if(abs(Random()%2==0))
+ setAnimation(i,backhandspringanim);
+ else
+ setAnimation(i,rollanim);
+ player[i].targetrotation+=90*(abs(Random()%2)*2-1);
+ player[i].wentforweapon=0;
+ }
+ if(player[i].targetanimation==jumpupanim||player[i].targetanimation==jumpdownanim)
+ setAnimation(i,flipanim);
+ }
+ }
+ player[i].forwardkeydown=0;
+ player[i].aiupdatedelay=.02;
+ }
+ //get confused by flips
+ if(player[0].isFlip()&&
+ !player[0].skeleton.free&&
+ player[0].targetanimation!=walljumprightkickanim&&
+ player[0].targetanimation!=walljumpleftkickanim){
+ if(findDistancefast(&player[0].coords,&player[i].coords)<25)
+ if((1-player[i].damage/player[i].damagetolerance)>.5)
+ player[i].stunned=1;
+ }
+ //go for weapon on the ground
+ if(player[i].wentforweapon<3)
+ for(int k=0;k<weapons.numweapons;k++)
+ if(player[i].creature!=wolftype)
+ if(player[i].num_weapons==0&&
+ weapons.owner[k]==-1&&
+ weapons.velocity[i].x==0&&
+ weapons.velocity[i].z==0&&
+ weapons.velocity[i].y==0){
+ if(findDistancefast(&player[i].coords,&weapons.position[k])<16){
+ player[i].wentforweapon++;
+ player[i].lastchecktime=6;
+ player[i].aitype=getweapontype;
+ player[i].ally=-1;
+ }
+ }
+ //dodge/reverse walljump kicks
+ if(player[i].damage<player[i].damagetolerance/2)
+ if(animation[player[i].targetanimation].height!=highheight)
+ if(player[i].damage<player[i].damagetolerance*.5&&
+ ((player[0].targetanimation==walljumprightkickanim||
+ player[0].targetanimation==walljumpleftkickanim)&&
+ ((player[i].aiupdatedelay<.15&&
+ difficulty==2)||
+ (player[i].aiupdatedelay<.08&&
+ difficulty!=2)))){
+ player[i].crouchkeydown=1;
+ }
+ //walked off a ledge (?)
+ if(player[i].isRun()&&!player[i].onground)
+ if(player[i].coords.y>terrain.getHeight(player[i].coords.x,player[i].coords.z)+10){
+ XYZ test2=player[i].coords+player[i].facing;
+ test2.y+=5;
+ XYZ test=player[i].coords+player[i].facing;
+ test.y-=10;
+ j=checkcollide(test2,test,player[i].laststanding);
+ if(j==-1)
+ j=checkcollide(test2,test);
+ if(j==-1){
+ player[i].velocity=0;
+ setAnimation(i,player[i].getStop());
+ player[i].targetrotation+=180;
+ player[i].stunned=.5;
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }else
+ player[i].laststanding=j;
+ }
+ //lose sight of player in the air (?)
+ if(player[0].coords.y>player[i].coords.y+5&&
+ animation[player[0].targetanimation].height!=highheight&&
+ !player[0].onterrain){
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ //it's time to think (?)
+ if(player[i].aiupdatedelay<0&&
+ !animation[player[i].targetanimation].attack&&
+ player[i].targetanimation!=staggerbackhighanim&&
+ player[i].targetanimation!=staggerbackhardanim&&
+ player[i].targetanimation!=backhandspringanim&&
+ player[i].targetanimation!=dodgebackanim){
+ //draw weapon
+ if(player[i].weaponactive==-1&&player[i].num_weapons>0)
+ player[i].drawkeydown=Random()%2;
+ else
+ player[i].drawkeydown=0;
+ player[i].rabbitkickenabled=Random()%2;
+ //chase player
+ XYZ rotatetarget=player[0].coords+player[0].velocity;
+ XYZ targetpoint=player[0].coords;
+ if(findDistancefast(&player[0].coords,&player[i].coords)<
+ findDistancefast(&rotatetarget,&player[i].coords))
+ targetpoint+=player[0].velocity*
+ findDistance(&player[0].coords,&player[i].coords)/findLength(&player[i].velocity);
+ player[i].targetrotation=roughDirectionTo(player[i].coords,targetpoint);
+ player[i].lookrotation=player[i].targetrotation;
+ player[i].aiupdatedelay=.2+fabs((float)(Random()%100)/1000);
+
+ if(findDistancefast(&player[i].coords,&player[0].coords)>5&&(player[0].weaponactive==-1||player[i].weaponactive!=-1))
+ player[i].forwardkeydown=1;
+ else if((findDistancefast(&player[i].coords,&player[0].coords)>16||
+ findDistancefast(&player[i].coords,&player[0].coords)<9)&&
+ player[0].weaponactive!=-1)
+ player[i].forwardkeydown=1;
+ else if(Random()%6==0||(player[i].creature==wolftype&&Random()%3==0))
+ player[i].forwardkeydown=1;
+ else
+ player[i].forwardkeydown=0;
+ //chill out around the corpse
+ if(player[0].dead){
+ player[i].forwardkeydown=0;
+ if(Random()%10==0)
+ player[i].forwardkeydown=1;
+ if(Random()%100==0){
+ player[i].aitype=pathfindtype;
+ player[i].finalfinaltarget=player[i].waypoints[player[i].waypoint];
+ player[i].finalpathfindpoint=-1;
+ player[i].targetpathfindpoint=-1;
+ player[i].lastpathfindpoint=-1;
+ player[i].lastpathfindpoint2=-1;
+ player[i].lastpathfindpoint3=-1;
+ player[i].lastpathfindpoint4=-1;
+ }
+ }
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].throwkeydown=0;
+
+ if(player[i].avoidcollided>.8&&!player[i].jumpkeydown&&player[i].collided<.8)
+ player[i].targetrotation+=90*(player[i].whichdirection*2-1);
+ //attack!!!
+ if(Random()%2==0||player[i].weaponactive!=-1||player[i].creature==wolftype)
+ player[i].attackkeydown=1;
+ else
+ player[i].attackkeydown=0;
+ if(player[i].isRun()&&Random()%6&&findDistancefast(&player[i].coords,&player[0].coords)>7)
+ player[i].attackkeydown=0;
+
+ //TODO: wat
+ if(player[i].aitype!=playercontrolled&&
+ (player[i].isIdle()||
+ player[i].isCrouch()||
+ player[i].isRun())){
+ int target=-2;
+ for(int j=0;j<numplayers;j++)
+ if(j!=i&&!player[j].skeleton.free&&
+ player[j].hasvictim&&
+ (tutoriallevel==1&&reversaltrain||
+ Random()%2==0&&difficulty==2||
+ Random()%4==0&&difficulty==1||
+ Random()%8==0&&difficulty==0||
+ player[j].lastattack2==player[j].targetanimation&&
+ player[j].lastattack3==player[j].targetanimation&&
+ (Random()%2==0||difficulty==2)||
+ (player[i].isIdle()||player[i].isRun())&&
+ player[j].weaponactive!=-1||
+ player[j].targetanimation==swordslashanim&&
+ player[i].weaponactive!=-1||
+ player[j].targetanimation==staffhitanim||
+ player[j].targetanimation==staffspinhitanim))
+ if(findDistancefast(&player[j].coords,&player[j].victim->coords)<4&&
+ player[j].victim==&player[i]&&
+ (player[j].targetanimation==sweepanim||
+ player[j].targetanimation==spinkickanim||
+ player[j].targetanimation==staffhitanim||
+ player[j].targetanimation==staffspinhitanim||
+ player[j].targetanimation==winduppunchanim||
+ player[j].targetanimation==upunchanim||
+ player[j].targetanimation==wolfslapanim||
+ player[j].targetanimation==knifeslashstartanim||
+ player[j].targetanimation==swordslashanim&&
+ (findDistancefast(&player[j].coords,&player[i].coords)<2||
+ player[i].weaponactive!=-1))){
+ if(target>=0)
+ target=-1;
+ else
+ target=j;
+ }
+ if(target>=0)
+ player[target].Reverse();
+ }
+
+ if(player[i].collided<1)
+ player[i].jumpkeydown=0;
+ if(player[i].collided>.8&&player[i].jumppower>=5||
+ findDistancefast(&player[i].coords,&player[0].coords)>400&&
+ player[i].onterrain&&
+ player[i].creature==rabbittype)
+ player[i].jumpkeydown=1;
+ //TODO: why are we controlling the human?
+ if(normaldotproduct(player[i].facing,player[0].coords-player[i].coords)>0)
+ player[0].jumpkeydown=0;
+ if(player[0].targetanimation==jumpdownanim&&
+ findDistancefast(&player[0].coords,&player[i].coords)<40)
+ player[i].crouchkeydown=1;
+ if(player[i].jumpkeydown)
+ player[i].attackkeydown=0;
+
+ if(tutoriallevel==1)
+ if(!canattack)
+ player[i].attackkeydown=0;
+
+
+ XYZ facing=player[i].coords;
+ XYZ flatfacing=player[0].coords;
+ facing.y+=playerJoint(i,head).position.y*player[i].scale;
+ flatfacing.y+=playerJoint(0,head).position.y*player[0].scale;
+ if(player[i].occluded>=2)
+ if(-1!=checkcollide(facing,flatfacing)){
+ if(!player[i].pause)
+ player[i].lastseentime-=.2;
+ if(player[i].lastseentime<=0&&
+ (player[i].creature!=wolftype||
+ player[i].weaponstuck==-1)){
+ player[i].aitype=searchtype;
+ player[i].lastchecktime=12;
+ player[i].lastseen=player[0].coords;
+ player[i].lastseentime=12;
+ }
+ }else
+ player[i].lastseentime=1;
+ }
+ }
+ if(animation[player[0].targetanimation].height==highheight&&
+ (player[i].aitype==attacktypecutoff||
+ player[i].aitype==searchtype))
+ if(player[0].coords.y>terrain.getHeight(player[0].coords.x,player[0].coords.z)+10){
+ XYZ test=player[0].coords;
+ test.y-=40;
+ if(-1==checkcollide(player[0].coords,test))
+ player[i].stunned=1;
+ }
+ //stunned
+ if(player[i].aitype==passivetype&&!(player[i].numwaypoints>1)||
+ player[i].stunned>0||
+ player[i].pause&&player[i].damage>player[i].superpermanentdamage){
+ if(player[i].pause)
+ player[i].lastseentime=1;
+ player[i].targetrotation=player[i].rotation;
+ player[i].forwardkeydown=0;
+ player[i].leftkeydown=0;
+ player[i].backkeydown=0;
+ player[i].rightkeydown=0;
+ player[i].jumpkeydown=0;
+ player[i].attackkeydown=0;
+ player[i].crouchkeydown=0;
+ player[i].throwkeydown=0;
+ }
+
+
+ XYZ facing;
+ facing=0;
+ facing.z=-1;
+
+ XYZ flatfacing=DoRotation(facing,0,player[i].rotation+180,0);
+ facing=flatfacing;
+
+ if(player[i].aitype==attacktypecutoff){
+ player[i].targetheadrotation=180-roughDirectionTo(player[i].coords,player[0].coords);
+ player[i].targetheadrotation2=pitchTo(player[i].coords,player[0].coords);
+ }else if(player[i].howactive>=typesleeping){
+ player[i].targetheadrotation=player[i].targetrotation;
+ player[i].targetheadrotation2=0;
+ }else{
+ if(player[i].interestdelay<=0){
+ player[i].interestdelay=.7+(float)(abs(Random()%100))/100;
+ player[i].headtarget=player[i].coords;
+ player[i].headtarget.x+=(float)(abs(Random()%200)-100)/100;
+ player[i].headtarget.z+=(float)(abs(Random()%200)-100)/100;
+ player[i].headtarget.y+=(float)(abs(Random()%200)-100)/300;
+ player[i].headtarget+=player[i].facing*1.5;
+ }
+ player[i].targetheadrotation=180-roughDirectionTo(player[i].coords,player[i].headtarget);
+ player[i].targetheadrotation2=pitchTo(player[i].coords,player[i].headtarget);
+ }
+ }
+}
+
+