// Person simulation and visualization
// Copyright (C) 2002 David Rosen
// Copyright (C) 2021 Nguyễn Gia Phong
//
// This file is part of Black Shades.
//
// Black Shades is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Black Shades is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Black Shades. If not, see .
#include
#include "Person.h"
extern float multiplier;
extern unsigned int gSourceID[100];
extern unsigned int gSampleSet[100];
extern Animation animation[30];
extern int thirdperson;
extern int visions;
extern Camera camera;
extern float rad2deg;
extern Model gunmodels[10];
extern Model skeletonmodels[10];
extern Sprites sprites;
extern float soundscalefactor;
extern int slomo;
extern int forwardskey;
extern int backwardskey;
extern int leftkey;
extern int rightkey;
extern int aimkey;
extern int psychicaimkey;
extern int psychickey;
extern Model skeletonmodels[10];
extern Costume costume[10];
HitStruct Person::BulletCollideWithPlayer(int who, XYZ start, XYZ end){
XYZ tempbulletloc[2];
XYZ collisionpoint;
GLfloat M[16];
int collide;
XYZ average;
int howmany;
float distancemax;
HitStruct hitstruct;
hitstruct.collision=0;
//Make bounding sphere
average=0;
howmany=0;
for(int j=0;jdistancemax){
distancemax=findDistancefast(average,skeleton.joints[j].position);
}
}
distancemax=sqrt(distancemax);
//Collide with player
if(skeleton.free<1){
start=start-playercoords;
end=end-playercoords;
if(playerrotation)start=DoRotation(start,0,-playerrotation,0);
if(playerrotation)end=DoRotation(end,0,-playerrotation,0);
}
tempbulletloc[0]=start;
tempbulletloc[1]=end;
if(sphere_line_intersection(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z,
tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z,
average.x, average.y, average.z, distancemax)){
for(int j=0;jposition.x)/2),
(-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2),
(-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2));
glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z);
glGetFloatv(GL_MODELVIEW_MATRIX,M);
tempbulletloc[0].x=M[12];
tempbulletloc[0].y=M[13];
tempbulletloc[0].z=M[14];
glPopMatrix();
glPushMatrix();
glLoadIdentity();
glScalef(1,1/skeleton.joints[j].length,1);
glRotatef(skeleton.joints[j].rotate2-90,0,0,1);
glRotatef(skeleton.joints[j].rotate1-90,0,1,0);
glTranslatef( (-(skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2),
(-(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2),
(-(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2));
glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z);
glGetFloatv(GL_MODELVIEW_MATRIX,M);
tempbulletloc[1].x=M[12];
tempbulletloc[1].y=M[13];
tempbulletloc[1].z=M[14];
glPopMatrix();
collide=skeletonmodels[skeleton.joints[j].modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint);
if(collide!=-1)
{
glPushMatrix();
glLoadIdentity();
glTranslatef( (skeleton.joints[j].position.x+skeleton.joints[j].parent->position.x)/2,
(skeleton.joints[j].position.y+skeleton.joints[j].parent->position.y)/2,
(skeleton.joints[j].position.z+skeleton.joints[j].parent->position.z)/2);
glRotatef(-skeleton.joints[j].rotate1+90,0,1,0);
glRotatef(-skeleton.joints[j].rotate2+90,0,0,1);
glScalef(1,skeleton.joints[j].length,1);
glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
glGetFloatv(GL_MODELVIEW_MATRIX,M);
collisionpoint.x=M[12];
collisionpoint.y=M[13];
collisionpoint.z=M[14];
glPopMatrix();
hitstruct.collision=1;
hitstruct.hitlocation=collisionpoint;
hitstruct.joint1=&skeleton.joints[j];
hitstruct.joint2=skeleton.joints[j].parent;
}
}
}
for(int j=0;jposition.x+skeleton.muscles[j].parent2->position.x)/2),
(-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2),
(-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2));
glTranslatef(tempbulletloc[0].x,tempbulletloc[0].y,tempbulletloc[0].z);
glGetFloatv(GL_MODELVIEW_MATRIX,M);
tempbulletloc[0].x=M[12];
tempbulletloc[0].y=M[13];
tempbulletloc[0].z=M[14];
glPopMatrix();
glPushMatrix();
glLoadIdentity();
glScalef(1,1/skeleton.muscles[j].length,1);
glRotatef(skeleton.muscles[j].rotate3,0,1,0);
glRotatef(skeleton.muscles[j].rotate2-90,0,0,1);
glRotatef(skeleton.muscles[j].rotate1-90,0,1,0);
glTranslatef( (-(skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2),
(-(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2),
(-(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2));
glTranslatef(tempbulletloc[1].x,tempbulletloc[1].y,tempbulletloc[1].z);
glGetFloatv(GL_MODELVIEW_MATRIX,M);
tempbulletloc[1].x=M[12];
tempbulletloc[1].y=M[13];
tempbulletloc[1].z=M[14];
glPopMatrix();
collide=skeletonmodels[skeleton.muscles[j].parent1->modelnum].LineCheck(tempbulletloc[0],tempbulletloc[1],&collisionpoint);
if(collide!=-1)
{
glPushMatrix();
glLoadIdentity();
glTranslatef( (skeleton.muscles[j].parent1->position.x+skeleton.muscles[j].parent2->position.x)/2,
(skeleton.muscles[j].parent1->position.y+skeleton.muscles[j].parent2->position.y)/2,
(skeleton.muscles[j].parent1->position.z+skeleton.muscles[j].parent2->position.z)/2);
glRotatef(-skeleton.muscles[j].rotate1+90,0,1,0);
glRotatef(-skeleton.muscles[j].rotate2+90,0,0,1);
glRotatef(-skeleton.muscles[j].rotate3,0,1,0);
glScalef(1,findDistance(skeleton.muscles[j].parent1->position,skeleton.muscles[j].parent2->position),1);
glTranslatef(collisionpoint.x,collisionpoint.y,collisionpoint.z);
glGetFloatv(GL_MODELVIEW_MATRIX,M);
collisionpoint.x=M[12];
collisionpoint.y=M[13];
collisionpoint.z=M[14];
glPopMatrix();
hitstruct.collision=1;
hitstruct.hitlocation=collisionpoint;
hitstruct.joint1=skeleton.muscles[j].parent1;
hitstruct.joint2=skeleton.muscles[j].parent2;
}
}
}
}
if(skeleton.free<1){
if(playerrotation)hitstruct.hitlocation=DoRotation(hitstruct.hitlocation,0,playerrotation,0);
hitstruct.hitlocation=hitstruct.hitlocation+playercoords;
}
return hitstruct;
}
extern float camerashake;
extern int cycle;
void Person::DoAnimations(int who)
{
if (target > 1 && !skeleton.free) {
// Footstep sounds
if (!slomo && !visions && (onground || abs(velocity.y) < 1)
&& (targetanimation == joganim
|| targetanimation == walkanim)
&& (targetframe == 0 || targetframe == 8) && who == 0) {
auto soundsrc = (playercoords - camera.position)
/ soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
int whichsound = footstepsound + abs(Random()) % 5;
alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[whichsound]);
}
if (targetanimation == zombieeatanim && targetframe == 3) {
auto& joints = skeleton.joints;
auto& jointlabels = skeleton.jointlabels;
auto head_joint = joints[jointlabels[head]];
auto soundsrc = (DoRotation(head_joint.position,
0, playerrotation, 0) + playercoords
- camera.position) / soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[bodyhitsound]);
bleeding = 1;
bleeddelay = 1;
bjoint1 = &head_joint;
bjoint2 = joints + jointlabels[neck];
}
currentanimation = targetanimation;
targetframe = currentframe + (backwardsanim ? -1 : 1);
if (targetframe >= animation[currentanimation].numframes)
targetframe = 0;
else if (targetframe < 0)
targetframe = animation[currentanimation].numframes - 1;
target = 0;
if ((currentanimation == getupfrontanim
|| currentanimation == getupbackanim) && targetframe == 0)
targetanimation = idleanim;
if (targetanimation == diveanim
&& currentanimation == diveanim && targetframe == 0) {
targetanimation = getupfrontanim;
auto& joints = skeleton.joints;
auto& jointlabels = skeleton.jointlabels;
auto head_joint = joints[jointlabels[head]];
auto soundsrc = (DoRotation(head_joint.position,
0, playerrotation, 0) + playercoords
- camera.position) / soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[bodywhacksound]);
}
if (currentanimation == throwanim && targetframe == 0)
targetanimation = idleanim;
if (currentanimation == thrownanim && targetframe == 0) {
skeleton.offset = 0;
skeleton.free = 1;
longdead = 1;
for (auto& joint : skeleton.joints) {
joint.position = playercoords
+ DoRotation(joint.position
+ joint.offset,
0, playerrotation, 0);
joint.realoldposition = joint.position;
joint.velocity = DoRotation(joint.velocity,
0, playerrotation, 0);
}
}
}
if(!skeleton.free){
if(currentanimation!=lyinganim){
if(animation[targetanimation].speed[currentframe]>animation[currentanimation].speed[currentframe])
target+=multiplier*animation[targetanimation].speed[currentframe]*speed;
if(animation[targetanimation].speed[currentframe]<=animation[currentanimation].speed[currentframe])
target+=multiplier*animation[currentanimation].speed[currentframe]*speed;
}
if(currentanimation==lyinganim){
target+=multiplier*animation[targetanimation].speed[targetframe]*speed;
}
if(((currentanimation==crouchanim)&&(targetanimation!=crouchanim))||((currentanimation!=crouchanim)&&(targetanimation==crouchanim)))target+=multiplier*animation[crouchanim].speed[0]*2;
if(currentanimation==idleanim&&targetanimation==idleanim)target-=multiplier*animation[idleanim].speed[0]/2;
if(target>1)currentframe=targetframe;
for(int i=0;i0||whichgun==grenade)&&whichgun!=nogun){
if(aiming&&targetanimation!=joganim){
if(aimamount<1)aimamount+=multiplier*4;
if(aimamount>1)aimamount=1;
}
if(!aiming||targetanimation==joganim){
if(aimamount>0)aimamount-=multiplier*4;
if(aimamount<0)aimamount=0;
}
if(grenphase==1){
if(grenamount<1)grenamount+=multiplier*4;
if(grenamount>1)grenamount=1;
}
if(grenphase==0){
if(grenamount>0)grenamount-=multiplier*4;
if(grenamount<0)grenamount=0;
}
rotatearound=skeleton.joints[skeleton.jointlabels[neck]].position;
for(int i=0;i0){
oldpos=skeleton.joints[i].position;
skeleton.joints[i].position=animation[grenadechargeanim].position[i][0];
if(currentanimation==crouchanim||targetanimation==crouchanim)skeleton.joints[i].position-=(animation[idleanim].position[skeleton.jointlabels[neck]][0]-skeleton.joints[skeleton.jointlabels[neck]].position);
skeleton.joints[i].position=skeleton.joints[i].position*(grenamount)+oldpos*(1-grenamount);
}
if(thirdperson||who!=0)skeleton.joints[i].position+=facingdown*.4;
if(currentanimation!=crouchanim)skeleton.joints[i].position-=facinghalf*recoil*.35;
if(currentanimation==crouchanim)skeleton.joints[i].position-=facinghalf*recoil*.1;
}
}
}
//Whack
if(attackframe>-1&&whichgun!=grenade){
for(int i=0;i0&&attackframe0)attacktarget+=multiplier*animation[riflehitanim].speed[attackframe-1]*2;
if(attacktarget>1){
attacktarget=0;
attackframe++;
if(attackframe>animation[riflehitanim].numframes)attackframe=-1;
}
}
//Throw grenade
if(attackframe>-1&&whichgun==grenade&&ammo>0){
for(int i=0;i0&&attackframe0)attacktarget+=multiplier*animation[grenadethrowanim].speed[attackframe-1]*2;
if(attacktarget>1){
attacktarget=0;
attackframe++;
if(attackframe>animation[grenadethrowanim].numframes){
attackframe=-1;
}
if(attackframe==animation[grenadethrowanim].numframes-1&&ammo>0){
ammo=-1;
sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*30+velocity, 1);
sprites.MakeSprite(spoonsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position,0,playerrotation,0)+playercoords, DoRotation(facing,0,playerrotation,0)*10+velocity, 1);
sprites.MakeSprite(pinsprite, 1, 1, 1, 1, DoRotation(skeleton.joints[skeleton.jointlabels[lefthand]].position,0,playerrotation,0)+playercoords, facing*.1+velocity, 1);
XYZ soundsrc = (DoRotation(skeleton.joints[skeleton.jointlabels[righthand]].position, 0, playerrotation, 0)
+ playercoords - camera.position) / soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[grenadethrowsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[grenadethrowsound]);
}
}
}
rotatearound=skeleton.joints[skeleton.jointlabels[abdomen]].position;
if(who==0)
for(int i=0;i 0) {
aiming = 0;
reloading -= multiplier;
}
if(ammo < 0 && reloads[whichgun] > 0 && reloading <= 0) {
ALint tempint;
alGetSourcei(gSourceID[reloadsound], AL_SOURCE_STATE, &tempint);
if (whichgun != grenade && tempint != AL_PLAYING) {
auto soundsrc = (playercoords - camera.position) / soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[reloadsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[reloadsound]);
}
reloading = 3;
aiming = 0;
switch (whichgun) {
case sniperrifle:
ammo = 5;
break;
case shotgun:
ammo = 6;
break;
case assaultrifle:
ammo = 25;
break;
case handgun1:
ammo = 12;
break;
case handgun2:
ammo = 16;
break;
case grenade:
ammo = 1;
reloading = 1;
break;
}
reloads[whichgun]--;
}
if (reloads[whichgun] == 0 && whichgun == grenade && ammo <= 0)
whichgun = nogun;
if (reloading < 0) {
reloading = 0;
aiming = 1;
}
}
}
}
void Person::DoAnimationslite(int who)
{
if (skeleton.free)
return;
if (target > 1) {
// Footstep sounds
if (who == 0 && !visions && (onground || abs(velocity.y) < 1)
&& (targetanimation == joganim
|| targetanimation == walkanim)
&& (targetframe == 0 || targetframe == 8)) {
auto soundsrc = (playercoords - camera.position)
/ soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
int whichsound = footstepsound + abs(Random()) % 5;
alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[whichsound]);
}
if (targetanimation == zombieeatanim && targetframe == 3) {
auto& joints = skeleton.joints;
auto& jointlabels = skeleton.jointlabels;
auto head_joint = joints[jointlabels[head]];
auto soundsrc = (DoRotation(head_joint.position,
0, playerrotation, 0) + playercoords
- camera.position) / soundscalefactor;
ALfloat gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[bodyhitsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[bodyhitsound]);
bleeding = 1;
bleeddelay = 1;
bjoint1 = &head_joint;
bjoint2 = joints + jointlabels[neck];
}
currentanimation = targetanimation;
targetframe = currentframe + (backwardsanim ? -1 : 1);
if (targetframe >= animation[currentanimation].numframes)
targetframe = 0;
else if (targetframe < 0)
targetframe = animation[currentanimation].numframes - 1;
target = 0;
if ((currentanimation == getupfrontanim
|| currentanimation == getupbackanim) && targetframe == 0)
targetanimation = idleanim;
}
if (currentanimation == lyinganim)
target += speed * multiplier
* animation[targetanimation].speed[targetframe];
else
target += speed * multiplier
* max(animation[currentanimation].speed[currentframe],
animation[targetanimation].speed[currentframe]);
if ((currentanimation == crouchanim) ^ (targetanimation == crouchanim))
target += *animation[crouchanim].speed * multiplier * 2;
if (currentanimation == idleanim && targetanimation == idleanim)
target -= *animation[idleanim].speed * multiplier / 2;
if (target > 1)
currentframe = targetframe;
}
void Person::DoStuff(int who){
int moveanim;
if((targetanimation!=idleanim&&targetanimation!=crouchanim)||visions==1)playerlowrotation=playerrotation;
if(targetanimation!=crouchanim&¤tanimation!=crouchanim){
if(playerrotation>playerlowrotation+50){playerlowrotation=playerrotation-50; targetanimation=walkanim; targetframe=0; target=0;}
if(playerrotationplayerlowrotation+70){playerrotation=playerlowrotation+70;}
if(playerrotationtemppoint2.x)gunrotate1=360-gunrotate1;
tempforward=target-start;
tempforward=DoRotation(tempforward,-90,0,0);
tempforward=DoRotation(tempforward,0,gunrotate1-90,0);
tempforward=DoRotation(tempforward,0,0,gunrotate2-90);
tempforward.y=0;
Normalise(&tempforward);
gunrotate3=acos(0-tempforward.z)*rad2deg;
if(0>tempforward.x)gunrotate3=360-gunrotate3;
}
float* determine_color(int model, int who, int whichcostume)
{
switch (model) {
case 0:
if (who != 0 || thirdperson)
return costume[whichcostume].headcolor;
break;
case 1:
if (who != 0 || thirdperson)
return costume[whichcostume].chestcolor;
break;
case 2:
return costume[whichcostume].abdomencolor;
case 3:
return costume[whichcostume].upperarmcolor;
case 4:
return costume[whichcostume].lowerarmcolor;
case 5:
return costume[whichcostume].handcolor;
case 6:
return costume[whichcostume].upperlegcolor;
case 7:
return costume[whichcostume].lowerlegcolor;
case 8:
return costume[whichcostume].footcolor;
}
return nullptr;
}
void draw_joint(Joint& joint, int who, int whichcostume)
{
if (!joint.hasparent || !joint.visible)
return;
glPushMatrix();
glTranslatef((joint.position.x + joint.parent->position.x) / 2,
(joint.position.y + joint.parent->position.y) / 2,
(joint.position.z + joint.parent->position.z) / 2);
glRotatef(90 - joint.rotate1, 0, 1, 0);
glRotatef(90 - joint.rotate2, 0, 0, 1);
glRotatef(-joint.rotate3, 0, 1, 0);
auto& model = joint.modelnum;
if (auto color = determine_color(model, who, whichcostume))
skeletonmodels[model].draw(*color, color[1], color[2]);
if (model == 0 && who == 0 && thirdperson)
skeletonmodels[9].draw();
glPopMatrix();
}
void draw_muscle(Muscle& mus, int who, int whichcostume)
{
if (!mus.visible)
return;
auto& pos1 = mus.parent1->position;
auto& pos2 = mus.parent2->position;
glPushMatrix();
glTranslatef((pos1.x + pos2.x) / 2,
(pos1.y + pos2.y) / 2, (pos1.z + pos2.z) / 2);
glRotatef(90 - mus.rotate1, 0, 1, 0);
glRotatef(90 - mus.rotate2, 0, 0, 1);
glRotatef(-mus.rotate3, 0, 1, 0);
auto& model = mus.parent1->modelnum;
if (auto color = determine_color(model, who, whichcostume))
skeletonmodels[model].draw(*color, color[1], color[2]);
if (model == 0 && who == 0 && thirdperson)
skeletonmodels[9].draw();
glPopMatrix();
}
int Person::DrawSkeleton(int who)
{
auto& left_hand = skeleton.jointlabels[lefthand];
auto& left_wrist = skeleton.joints[left_hand].position;
auto& right_hand = skeleton.jointlabels[righthand];
auto& right_wrist = skeleton.joints[right_hand].position;
auto& head_pos = skeleton.joints[skeleton.jointlabels[head]].position;
auto& neck_pos = skeleton.joints[skeleton.jointlabels[neck]].position;
switch (whichgun) {
case sniperrifle:
FindRotationGun(right_wrist, left_wrist);
glPushMatrix();
glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z);
glRotatef(90 - gunrotate1, 0, 1, 0);
glRotatef(90 - gunrotate2, 0, 0, 1);
glRotatef(-gunrotate3, 0, 1, 0);
gunmodels[sniperriflemodel].draw();
glPopMatrix();
break;
case shotgun:
FindRotationGun(right_wrist, left_wrist);
glPushMatrix();
glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z);
glRotatef(2, 1, 0, 0);
glRotatef(90 + 1 - gunrotate1, 0, 1, 0);
glRotatef(90 - gunrotate2, 0, 0, 1);
glRotatef(-gunrotate3, 0, 1, 0);
glTranslatef(0, -0.4, 0);
gunmodels[shotgunmodel].draw();
glPopMatrix();
break;
case assaultrifle:
FindRotationGun(right_wrist, left_wrist);
glPushMatrix();
glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z);
glRotatef(90 - gunrotate1, 0, 1, 0);
glRotatef(90 - gunrotate2, 0, 0, 1);
glRotatef(-gunrotate3, 0, 1, 0);
gunmodels[assaultriflemodel].draw();
glPopMatrix();
break;
case handgun1:
case handgun2:
if (who || thirdperson)
FindRotationGun(right_wrist,
head_pos * 0.35 + neck_pos * 0.65);
else
FindRotationGun(right_wrist,
head_pos * 0.65 + neck_pos * 0.35);
glPushMatrix();
glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z);
glRotatef(90 - 1.5 - gunrotate1, 0, 1, 0);
glRotatef(90 - gunrotate2, 0, 0, 1);
glRotatef(-gunrotate3, 0, 1, 0);
glTranslatef(0, 0, 0.15);
if (whichgun == handgun1)
gunmodels[handgunbasemodel].draw();
else
gunmodels[handgun2basemodel].draw();
glTranslatef(0, recoil * -0.3, 0);
if (whichgun == handgun1)
gunmodels[handgunslidemodel].draw();
else
gunmodels[handgun2slidemodel].draw();
glPopMatrix();
break;
case grenade:
glPushMatrix();
glTranslatef(right_wrist.x, right_wrist.y, right_wrist.z);
glRotatef(-90, 1, 0, 0);
glTranslatef(0, 0, 0.05);
if (reloading <= 0) {
gunmodels[grenadebasemodel].draw();
if (grenphase == 0)
gunmodels[grenadepinmodel].draw();
glTranslatef(0, 0, 0.005);
gunmodels[grenadespoonmodel].draw();
}
glPopMatrix();
glPushMatrix();
glTranslatef(left_wrist.x, left_wrist.y, left_wrist.z);
glRotatef(-90, 1, 0, 0);
glTranslatef(0, 0, -0.15);
if (reloading <= 0 && grenphase == 1)
gunmodels[grenadepinmodel].draw();
glPopMatrix();
break;
case knife:
auto& wrist = skeleton.joints[skeleton.jointlabels[righthand]];
glPushMatrix();
glTranslatef(wrist.position.x,
wrist.position.y, wrist.position.z);
glRotatef(90 - 1.5 - wrist.rotate1, 0, 1, 0);
glRotatef(90 - wrist.rotate2, 0, 0, 1);
glRotatef(-wrist.rotate3, 0, 1, 0);
glTranslatef(0, -0.2, 0);
gunmodels[knifemodel].draw();
glPopMatrix();
break;
}
if (litup) {
GLfloat LightAmbient[] {0, 0, 0, 1.0f};
GLfloat LightDiffuse[] {1, 1, 1, 1.0f};
auto& hand = skeleton.jointlabels[lefthand];
XYZ lightpoint = skeleton.joints[hand].position;
GLfloat LightPosition[] {lightpoint.x,
lightpoint.y, lightpoint.z, 0};
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
glEnable(GL_LIGHT1);
litup = 0;
} else {
glDisable(GL_LIGHT1);
}
//Find forward vectors
if (!who || skeleton.free || skeleton.offset || whichgun != nogun
|| currentanimation == lyinganim
|| ((currentanimation == getupfrontanim
|| currentanimation == getupbackanim)
&& targetanimation == idleanim)) {
if (skeleton.free != 1 || longdead > 0) {
if (skeleton.offset && skeleton.free < 1) {
XYZ normal;
skeleton.offset = 0;
for (int i = 0; i < skeleton.num_joints; i++) {
auto& joint = skeleton.joints[i];
joint.oldposition = joint.position;
joint.position += joint.offset;
if (findLengthfast(joint.offset) >= multiplier * multiplier * 25) {
normal = joint.offset;
Normalise(&normal);
skeleton.offset = 1;
joint.offset -= normal * multiplier * 5;
} else {
joint.offset=0;
}
}
skeleton.DoConstraints();
}
auto& fwdjoints = skeleton.forwardjoints;
CrossProduct(skeleton.joints[fwdjoints[1]].position
- skeleton.joints[fwdjoints[0]].position,
skeleton.joints[fwdjoints[2]].position
- skeleton.joints[fwdjoints[0]].position,
&skeleton.forward);
Normalise(&skeleton.forward);
auto& lowfwd = skeleton.lowforwardjoints;
CrossProduct(skeleton.joints[lowfwd[1]].position
- skeleton.joints[lowfwd[0]].position,
skeleton.joints[lowfwd[2]].position
- skeleton.joints[lowfwd[0]].position,
&skeleton.lowforward);
Normalise(&skeleton.lowforward);
// Special forwards
auto specialfwd = skeleton.specialforward;
*specialfwd++ = skeleton.forward;
auto& right_shoulder = skeleton.jointlabels[rightshoulder];
auto& right_elbow = skeleton.jointlabels[rightelbow];
*specialfwd = skeleton.joints[right_elbow].position
- skeleton.joints[right_shoulder].position / 2
- right_wrist / 2 + skeleton.forward * 0.2;
Normalise(specialfwd++);
auto& left_shoulder = skeleton.jointlabels[leftshoulder];
auto& left_elbow = skeleton.jointlabels[leftelbow];
*specialfwd = skeleton.joints[left_elbow].position
- skeleton.joints[left_shoulder].position / 2
- left_wrist / 2 + skeleton.forward * 0.2;
Normalise(specialfwd++);
if(!who && aimamount > 0
&& health == 100 && whichgun != nogun) {
//Facing
XYZ facing {0};
facing.z = 1;
facing = DoRotation(facing, camera.rotation2, 0, 0);
XYZ facingdown = DoRotation(facing, 90, 0, 0);
skeleton.specialforward[1] *= 1 - aimamount;
skeleton.specialforward[1] += facingdown * aimamount;
skeleton.specialforward[2] *= 1 - aimamount;
skeleton.specialforward[2] += facingdown * aimamount;
}
auto& right_hip = skeleton.jointlabels[righthip];
auto& right_ankle = skeleton.jointlabels[rightankle];
auto& right_knee = skeleton.jointlabels[rightknee];
*specialfwd = skeleton.joints[right_hip].position / 2
+ skeleton.joints[right_ankle].position / 2
- skeleton.joints[right_knee].position
+ skeleton.lowforward * 0.2;
Normalise(specialfwd++);
auto& left_hip = skeleton.jointlabels[lefthip];
auto& left_ankle = skeleton.jointlabels[leftankle];
auto& left_knee = skeleton.jointlabels[leftknee];
*specialfwd = skeleton.joints[left_hip].position / 2
+ skeleton.joints[left_ankle].position / 2
- skeleton.joints[left_knee].position
+ skeleton.lowforward * 0.2;
Normalise(specialfwd++);
for(int i = 0; i < skeleton.num_joints; i++)
if (skeleton.joints[i].hasparent
&& skeleton.joints[i].visible)
skeleton.FindRotationJoint(i);
for(int i = 0; i < skeleton.num_muscles; i++)
if (skeleton.muscles[i].visible)
skeleton.FindRotationMuscle(i);
}
}
for (int i = 0; i < skeleton.num_joints; i++)
draw_joint(skeleton.joints[i], who, whichcostume);
for (int i = 0; i < skeleton.num_muscles; i++)
draw_muscle(skeleton.muscles[i], who, whichcostume);
if (skeleton.offset && skeleton.free < 1)
for (int i = 0; i < skeleton.num_joints; i++) {
auto& joint = skeleton.joints[i];
joint.position = joint.oldposition;
}
glDisable(GL_LIGHT1);
return 0;
}