// Game tick handling
// Copyright (C) 2002 David Rosen
// Copyright (C) 2003 Ryan C. Gordon
// Copyright (C) 2003 Dan Olson
// Copyright (C) 2003 Steven Fuller
// Copyright (C) 2003 Zachary Jack Slater
// Copyright (C) 2003 Toby Haynes
// 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 "Game.h"
extern float multiplier;
extern int thirdperson;
extern int visions;
extern Sprites sprites;
extern unsigned int gSourceID[100];
extern unsigned int gSampleSet[100];
extern Camera camera;
extern float camerashake;
extern Fog fog;
extern int environment;
extern float precipitationhorz;
extern float precipitationvert;
extern float snowdelay;
extern float precipitationdensity;
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 Decals decals;
#define maxfallvel 40
void Game::Splat(int k)
{
if (k && visions)
return;
auto& skeleton = person[k].skeleton;
skeleton.free = 1;
skeleton.offset = 0;
person[k].health = 0;
person[k].longdead = person[k].bleeding = person[k].bleeddelay = 1;
person[k].DoAnimations(k);
auto& joints = skeleton.joints;
auto& head_joint = joints[skeleton.jointlabels[head]];
person[k].bjoint1 = &head_joint;
person[k].bjoint2 = joints + skeleton.jointlabels[neck];
for (auto& joint : joints) {
joint.position = DoRotation(joint.position + joint.offset, 0,
person[k].playerrotation, 0) + person[k].playercoords;
joint.realoldposition = joint.position;
joint.velocity = {0, person[k].velocity.y, 0};
}
auto soundpos = head_joint.position - camera.position;
ALfloat gLoc[] {
soundpos.x / soundscalefactor,
soundpos.y / soundscalefactor,
soundpos.z / soundscalefactor,
};
alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[headwhacksound]);
}
void Game::saveHighScore()
{
if (score > highscore) {
highscore = score;
/* TODO */
ofstream opstream("highscore.txt");
opstream << highscore;
opstream << "\n";
opstream << beatgame;
opstream.close();
}
}
void Game::updateSong()
{
if (environment == rainy_environment)
alSourcePlay(gSourceID[rainsound]);
else
alSourcePause(gSourceID[rainsound]);
alSourceStop(gSourceID[whichsong]);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
if (type == zombie_type)
whichsong = zombiesong;
else if (person[0].whichgun == knife)
whichsong = knifesong;
else
whichsong = shootsong;
alSourcef(gSourceID[whichsong], AL_PITCH, 1);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
alSourcePlay(gSourceID[whichsong]);
}
void Game::handleMenu()
{
GetMouse(&mouseloc);
float mousex = (float) mouseloc.h * 640 / screenwidth;
float mousey = 480 - (float) mouseloc.v * 480 / screenheight;
int button = Button();
oldmouseoverbutton = mouseoverbutton;
mouseoverbutton = 0;
if (mousex > 120 && mousex < 560 && button && !oldbutton) {
if (mousey > 235 && mousey < 305)
mouseoverbutton = 1;
else if (mousey > 112 && mousey < 182)
mouseoverbutton = 2;
} else if (!mainmenuness) {
mouseoverbutton = 1;
}
oldbutton = button;
switch (mouseoverbutton) {
case 1:
updateSong();
flashamount = flashr = flashg = flashb = 1;
alSourcePlay(gSourceID[soulinsound]);
if (!gameinprogress) {
mission = 0;
initGame(this);
}
GetMouse(&mouseloc);
if (visions)
alSourcePlay(gSourceID[visionsound]);
gameinprogress = 1;
mainmenu = 0;
break;
case 2:
if (gameinprogress) {
flashamount = flashr = flashg = flashb = 1;
gameinprogress = 0;
} else {
flashamount = flashr = 1;
flashg = flashb = 0;
glfwSetWindowShouldClose(glfwGetCurrentContext(), true);
}
alSourcePlay(gSourceID[losesound]);
saveHighScore();
break;
}
}
void Game::mouseLook()
{
if ((person[0].aimamount <= 0
&& person[0].targetanimation != crouchanim)) {
camera.rotation = camera.visrotation;
camera.rotation2 = camera.visrotation2;
mousesensitivity = usermousesensitivity;
} else if (person[0].aimamount >= 1 && !zoom) {
mousesensitivity = usermousesensitivity * 0.8;
}
if (slomo == 2)
mousesensitivity *= 0.6;
GetMouseRel(&mouseloc);
auto factor = mousesensitivity / 1.3888;
mouserotation = mouseloc.h * factor;
mouserotation2 = mouseloc.v * factor;
if (abs(mouseloc.h) < 400)
camera.rotation += mouserotation;
if (abs(mouseloc.v) < 200)
camera.rotation2 += mouserotation2;
auto hrot = factor * 500;
if (mouseloc.h > 400)
camera.rotation += mouserotation - hrot;
if (mouseloc.h < -400)
camera.rotation += mouserotation + hrot;
auto vrot = factor * 300;
if (mouseloc.v > 200)
camera.rotation2 += mouserotation2 - vrot;
if (mouseloc.v < -200)
camera.rotation2 += mouserotation2 + vrot;
camera.rotation2 = min(max(camera.rotation2, -89.0f), 89.0f);
// Smooth
camera.rotation = camera.rotation * 0.7 + camera.oldrotation * 0.3;
camera.rotation2 = camera.rotation2 * 0.7 + camera.oldrotation2 * 0.3;
if (zoom || visions || person[0].aimamount <= 0
|| person[0].whichgun == nogun
|| person[0].whichgun == grenade
|| person[0].whichgun == knife) {
camera.visrotation = camera.rotation;
camera.visrotation2 = camera.rotation2;
} else {
camera.visrotation = min(camera.rotation + 7,
max(camera.rotation - 7, camera.visrotation));
camera.visrotation2 = min(camera.rotation2 + 15,
max(camera.rotation2 - 15, camera.visrotation2));
}
person[0].playerrotation = 180 - camera.rotation;
camera.oldrotation = camera.rotation;
camera.oldrotation2 = camera.rotation2;
}
void Game::setListener(XYZ& facing)
{
XYZ upvector {0, 0, -1};
upvector = DoRotation(upvector, -camera.rotation2 + 90, 0, 0);
upvector = DoRotation(upvector, 0, -camera.rotation, 0);
ALfloat ori[] {
facing.x, facing.y, facing.z,
-upvector.x, upvector.y, upvector.z,
};
alListenerfv(AL_ORIENTATION, ori);
}
XYZ Game::aimPlayer()
{
auto& joints = person[0].skeleton.joints;
auto& jointlabels = person[0].skeleton.jointlabels;
auto point = joints[jointlabels[lefthand]].position
- joints[jointlabels[righthand]].position;
float aimrot = 0.0f, aimrot2 = 0.0f;
switch (person[0].whichgun) {
case assaultrifle:
aimrot = -2.5f;
break;
case sniperrifle:
aimrot = 4.0f;
break;
case shotgun:
aimrot = Random() % 1000 / 500.0f - 1;
aimrot2 = Random() % 1000 / 500.0f + 2;
break;
case handgun1:
case handgun2:
aimrot = -0.9f;
auto k = thirdperson ? 0.35 : 0.65;
point = joints[jointlabels[righthand]].position
- joints[jointlabels[head]].position * k
- joints[jointlabels[neck]].position * (1 - k);
break;
}
return DoRotation(point, aimrot2,
person[0].playerrotation + aimrot, 0);
}
XYZ Game::aimBot(int j)
{
float inaccuracy = 0.0f;
switch (person[j].whichgun) {
case handgun1:
case handgun2:
inaccuracy = 8.0f;
break;
case assaultrifle:
case shotgun:
inaccuracy = 6.0f;
break;
case sniperrifle:
inaccuracy = 2.0f;
break;
}
if (person[person[j].killtarget].skeleton.free)
inaccuracy *= 3;
auto& target = person[person[j].killtarget];
auto& joints = target.skeleton.joints;
auto& jointlabels = target.skeleton.jointlabels;
XYZ aim = joints[jointlabels[abdomen]].position;
if (target.skeleton.free)
inaccuracy *= 3;
else
aim = DoRotation(aim, 0, target.playerrotation, 0)
+ target.playercoords;
auto& lefthandpos = joints[jointlabels[lefthand]].position;
aim -= person[j].playercoords
+ DoRotation(lefthandpos, 0, person[j].playerrotation, 0);
return DoRotation(
DoRotation(
DoRotation(aim, 0, -person[j].playerrotation, 0),
(abs(Random() % 2000) / 2000.0 - 0.5) * inaccuracy,
(abs(Random() % 2000) / 2000.0 - 0.5) * inaccuracy, 0),
0, person[j].playerrotation, 0);
}
void Game::Tick()
{
if (mainmenu) {
handleMenu();
return;
}
if (person[1].health <= 0 || person[0].health <= 0 || killedinnocent)
losedelay -= multiplier / 6;
else
timeremaining -= multiplier * 25 / 40;
if (timeremaining <= 0) {
score += ++mission * 50 + 100;
flashamount = flashg = 1;
flashr = flashb = 0;
alSourcePlay(gSourceID[souloutsound]);
if (mission >= nummissions) {
alSourcePause(gSourceID[rainsound]);
alSourceStop(gSourceID[visionsound]);
alSourceStop(gSourceID[whichsong]);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
whichsong = mainmenusong;
alSourcef(gSourceID[whichsong], AL_PITCH, 1);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
alSourcePlay(gSourceID[whichsong]);
mainmenu = beatgame = 1;
gameinprogress = 0;
saveHighScore();
} else {
updateSong();
initGame(this);
}
}
if (losedelay <= 0) {
score -= (person[murderer].health > 0) ? 200 : 100;
flashamount = 1;
flashr = flashg = flashb = 0;
alSourcePlay(gSourceID[soulinsound]);
updateSong();
initGame(this);
}
sprites.DoStuff();
decals.DoStuff();
// Facing
XYZ facing {0, 0, -1};
facing = DoRotation(facing, -camera.rotation2, 0, 0);
facing = DoRotation(facing, 0, -camera.rotation, 0);
XYZ flatfacing = facing;
flatfacing.y = 0;
Normalise(&flatfacing);
mouseLook();
//Check collision with buildings
int beginx,endx;
int beginz,endz;
XYZ collpoint;
XYZ move;
int whichtri;
XYZ underpoint;
XYZ overpoint;
int pointnum;
float depth;
XYZ normalrotated;
bool inblock;
//Check people collisions
for(int k=0;knum_blocks-1)endx=num_blocks-1;
endz=(person[k].playercoords.z+block_spacing/2)/block_spacing+1;
if(endz>num_blocks-1)endz=num_blocks-1;
/* TODO: huh?
* if(k!=0) {
* beginx == person[k].whichblockx;
* beginz == person[k].whichblocky;
* endx == person[k].whichblockx;
* endz == person[k].whichblocky;
* }
*/
if(beginx<=endx&&beginz<=endz)
for(int i=beginx;i<=endx;i++)
for(int j=beginz;j<=endz;j++){
inblock=0;
//Ground collision
move=0;
move.x=i*block_spacing;
move.z=j*block_spacing;
whichtri=sidewalkcollide.LineCheck2(overpoint,underpoint,&collpoint,move,cityrotation[i][j]*90);
if(whichtri!=-1&&person[k].playercoords.y<=collpoint.y&&person[k].velocity.y<=0){
person[k].playercoords.y=collpoint.y;
person[k].onground=1;
if(person[k].velocity.y<-maxfallvel)Splat(k);
else person[k].velocity.y=0;
}
if(whichtri!=-1){
inblock=1;
if(k==0){onblockx=i;onblocky=j;}
}
//Wall collision
if(k==0){
if(inblock){
for(int l=0;l<8;l++){
move=0;
move.x=i*block_spacing;
move.z=j*block_spacing;
whichtri=blockwalls[citytype[i][j]].LineCheck3(person[k].oldplayercoords+boundingpoints[l],person[k].playercoords+boundingpoints[l],&collpoint,move,cityrotation[i][j]*90,&depth);
if(whichtri!=-1){
normalrotated=DoRotation(blockwalls[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
person[k].playercoords+=normalrotated*(-(dotproduct(normalrotated,person[k].playercoords-person[k].oldplayercoords))-depth);
}
}
for(int l=0;l<8;l++){
pointnum=k+1;
if(pointnum>3)pointnum=0;
move=0;
move.x=i*block_spacing;
move.z=j*block_spacing;
whichtri=blockwalls[citytype[i][j]].LineCheck3(person[k].playercoords+boundingpoints[l],person[k].playercoords+boundingpoints[pointnum],&collpoint,move,cityrotation[i][j]*90,&depth);
if(whichtri!=-1){
normalrotated=DoRotation(blockwalls[citytype[i][j]].normals[whichtri],0,cityrotation[i][j]*90,0);
person[k].playercoords+=normalrotated;
}
}
}
//Roof collision
if(inblock&&person[k].playercoords.y>30){
if(!person[k].onground){
move=0;
move.x=i*block_spacing;
move.z=j*block_spacing;
whichtri=blockroofs[citytype[i][j]].LineCheck2(overpoint,underpoint,&collpoint,move,cityrotation[i][j]*90);
if(whichtri!=-1&&person[k].playercoords.y<=collpoint.y&&person[k].velocity.y<=0){
person[k].playercoords.y=collpoint.y;
person[k].onground=1;
if(person[k].velocity.y<-maxfallvel)Splat(k);
else person[k].velocity.y=0;
}
if(whichtri!=-1)inblock=1;
}
}
}
}
if (person[k].playercoords.y <= 0) {
person[k].onground = 1;
person[k].playercoords.y = 0;
if (person[k].velocity.y<-maxfallvel)
Splat(k);
else
person[k].velocity.y = 0;
if (k == 0)
onblockx = onblocky = -1;
}
// SBF - this is definately in the wrong spot!
//person[k].oldplayercoords=person[k].playercoords;
}
}
}
//Camera
camera.oldposition=camera.position;
camera.targetoffset=0;
camera.targetoffset.z=-5;
// Spawn people
int cyclenum = 0;
int blockspawnx = 0, blockspawny = 0;
do {
auto block = person[0].playercoords / block_spacing;
blockspawnx = block.x + 0.5f + Random() % 2;
blockspawny = block.z + 0.5f + Random() % 2;
auto& people = citypeoplenum[blockspawnx][blockspawny];
if (people < max_people_block)
break;
} while (++cyclenum < 10);
spawndelay -= multiplier;
if(cyclenum<10){
if(spawndelay<0&&numpeople=max_people_block&&cyclenum<10)||blockspawnx==0||(blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky)){
blockspawnx=((person[0].playercoords.x+block_spacing/2)/block_spacing)+Random()%2;
blockspawny=((person[0].playercoords.z+block_spacing/2)/block_spacing)+Random()%2;
cyclenum++;
}
}
person[numpeople].playerrotation=0;
person[numpeople].whichcostume=casualcostumes+abs(Random())%numcasual;
person[numpeople].whichblockx=blockspawnx;
person[numpeople].whichblocky=blockspawny;
person[numpeople].pathnum=-1;
person[numpeople].oldpathnum=-1;
person[numpeople].oldoldpathnum=-1;
person[numpeople].oldoldoldpathnum=-1;
while(person[numpeople].pathnum<0||person[numpeople].pathnum>=path.vertexNum||person[numpeople].pathnum==1){
person[numpeople].pathnum=Random()%path.vertexNum;
}
person[numpeople].pathtarget.x=path.vertex[person[numpeople].pathnum].x;
person[numpeople].pathtarget.z=path.vertex[person[numpeople].pathnum].z;
person[numpeople].pathsize=.98+float(abs(Random()%20))/400;
person[numpeople].pathtarget*=person[numpeople].pathsize;
person[numpeople].pathtarget.x+=person[numpeople].whichblockx*block_spacing;
person[numpeople].pathtarget.z+=person[numpeople].whichblocky*block_spacing;
person[numpeople].playercoords=person[numpeople].pathtarget;
person[numpeople].oldplayercoords=person[numpeople].playercoords;
person[numpeople].skeleton.free=0;
person[numpeople].targetanimation=walkanim;
if(person[numpeople].type==zombietype)person[numpeople].targetanimation=zombiewalkanim;
person[numpeople].speed=1;
person[numpeople].existing=0;
person[numpeople].speedmult=.8+float(abs(Random()%20))/50;
person[numpeople].health=100;
person[numpeople].maxhealth=100;
person[numpeople].playerrotation2=0;
person[numpeople].lastdistancevictim=200000;
if(person[numpeople].skeleton.broken)person[numpeople].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
if(numpeople==1)person[numpeople].type=viptype;
person[numpeople].killtarget=-1;
if(person[numpeople].type==eviltype){person[numpeople].existing=1; person[numpeople].pathsize=1.04; person[numpeople].whichgun=nogun; person[numpeople].aiming=1; person[numpeople].killtarget=-1; person[numpeople].speedmult=1+.3*difficulty;}
if(person[numpeople].type==zombietype){person[numpeople].existing=1; person[numpeople].pathsize=1.04; person[numpeople].whichgun=nogun; person[numpeople].aiming=0; person[numpeople].killtarget=-1; person[numpeople].speedmult=0.7+.2*difficulty;}
else {person[numpeople].whichgun=nogun; person[numpeople].aiming=0; person[numpeople].killtarget=-1;}
if(person[numpeople].type==viptype){person[numpeople].existing=1;}
if(enemystate==2)person[numpeople].killtarget=1;
numpeople++;
citypeoplenum[blockspawnx][blockspawny]++;
spawndelay=.1;
}
if(spawndelay<0&&numpeople>=max_people){
if(cycle>=max_people)cycle=0;
cyclenum=0;
while(cyclenum=max_people)cycle=0;
}
if(cycle=max_people_block&&cyclenum<10)||blockspawnx==0||(blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky)){
blockspawnx=((person[0].playercoords.x+block_spacing/2)/block_spacing)+Random()%2;
blockspawny=((person[0].playercoords.z+block_spacing/2)/block_spacing)+Random()%2;
cyclenum++;
}
}
person[cycle].playerrotation=0;
person[cycle].whichcostume=casualcostumes+abs(Random())%numcasual;
citypeoplenum[person[cycle].whichblockx][person[cycle].whichblocky]--;
person[cycle].whichblockx=blockspawnx;
person[cycle].whichblocky=blockspawny;
person[cycle].pathnum=-1;
person[cycle].oldpathnum=-1;
person[cycle].oldoldpathnum=-1;
person[cycle].oldoldoldpathnum=-1;
while(person[cycle].pathnum<0||person[cycle].pathnum>=path.vertexNum||person[cycle].pathnum==1){
person[cycle].pathnum=Random()%path.vertexNum;
}
person[cycle].pathtarget.x=path.vertex[person[cycle].pathnum].x;
person[cycle].pathtarget.z=path.vertex[person[cycle].pathnum].z;
person[cycle].pathsize=.98+float(abs(Random()%20))/400;
person[cycle].pathtarget*=person[cycle].pathsize;
person[cycle].pathtarget.x+=person[cycle].whichblockx*block_spacing;
person[cycle].pathtarget.z+=person[cycle].whichblocky*block_spacing;
person[cycle].playercoords=person[cycle].pathtarget;
person[cycle].oldplayercoords=person[cycle].playercoords;
person[cycle].skeleton.free=0;
person[cycle].targetanimation=walkanim;
if(person[cycle].type==zombietype)person[cycle].targetanimation=zombiewalkanim;
person[cycle].speed=1;
person[cycle].existing=0;
person[cycle].speedmult=.8+float(abs(Random()%20))/50;
person[cycle].health=100;
person[cycle].maxhealth=100;
person[cycle].playerrotation2=0;
if(person[cycle].skeleton.broken)person[cycle].skeleton.Load((char *)":Data:Skeleton:Basic Figure");
if(enemystate==1)person[cycle].killtarget=-1;
if(person[cycle].type==eviltype){person[cycle].existing=1; person[cycle].pathsize=1.04; person[cycle].whichgun=nogun; person[cycle].aiming=1; person[cycle].killtarget=-1; person[cycle].speedmult=1+.3*difficulty;}
if(person[cycle].type==zombietype){person[cycle].existing=1; person[cycle].pathsize=1.04; person[cycle].whichgun=nogun; person[cycle].aiming=0; person[cycle].killtarget=-1; person[cycle].speedmult=.7+.2*difficulty;}
else {person[cycle].whichgun=nogun; person[cycle].aiming=0; person[cycle].killtarget=-1;}
person[cycle].lastdistancevictim=200000;
if(enemystate==2)person[cycle].killtarget=1;
if(numpeople=0){
decals.MakeDecal(bloodpool,temp,12,normish, whichtri, &sidewalkcollide, move, cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
}
if(whichtri==-1){
temp=person[i].skeleton.joints[person[i].skeleton.jointlabels[abdomen]].position;
temp.y=-.5;
move=0;
decals.MakeDecal(bloodpool,temp,12,normish, 0, &sidewalkcollide, move, 0);
}
person[i].firstlongdead=1;
}
}
if(person[i].health<100&&person[i].type!=zombietype){
person[i].health-=multiplier*120;
}
if(person[i].health<100&&person[i].type==zombietype){
person[i].health+=multiplier*10;
if(person[i].health>person[i].maxhealth)person[i].health=person[i].maxhealth;
}
if(person[i].health<100&&person[i].type==zombietype&&person[i].skeleton.free==1){
person[i].health+=multiplier*10;
if(person[i].health>person[i].maxhealth)person[i].health=person[i].maxhealth;
}
if(person[i].health<40&&person[i].type==zombietype){
person[i].speedmult-=multiplier/20;
if(person[i].speedmult<.6){
person[i].speedmult=.6;
person[i].killtarget=-1;
}
}
if(person[i].health>=40&&person[i].type==zombietype){
person[i].speedmult+=multiplier/40;
if(person[i].speedmult>.7+difficulty*.2){
person[i].speedmult=.7+difficulty*.2;
person[i].killtarget=1;
}
}
if(person[i].maxhealth<100&&person[i].type==zombietype){
person[i].maxhealth+=multiplier*2;
if(person[i].maxhealth>100)person[i].maxhealth=100;
}
if(person[i].bleeding>0){
person[i].bleeding-=multiplier;
person[i].bleeddelay-=multiplier*10;
if(person[i].bleeddelay<=0){
person[i].bleeddelay=1;
if(person[i].skeleton.free==0){
bleedloc=DoRotation((person[i].bjoint1->position+person[i].bjoint2->position)/2,0,person[i].playerrotation,0)+person[i].playercoords;
}
if(person[i].skeleton.free>0){
bleedloc=(person[i].bjoint1->position+person[i].bjoint2->position)/2;
}
vel=0;
sprites.MakeSprite(bloodspritedown, .6, 1, .2, .2,bleedloc, vel, 3*person[i].bleeding);
}
}
if(person[i].skeleton.free==0){
//Gun
if(person[i].type==playertype||person[i].type==eviltype){
if(i==0){
if(person[i].whichgun==shotgun)person[i].recoil-=multiplier*4;
if(person[i].whichgun==sniperrifle)person[i].recoil-=multiplier*2;
if(person[i].whichgun==handgun1)person[i].recoil-=multiplier*5;
if(person[i].whichgun==handgun2)person[i].recoil-=multiplier*5;
if(person[i].whichgun==assaultrifle)person[i].recoil-=multiplier*10;
}
if(i!=0){
if(person[i].whichgun==shotgun)person[i].recoil-=multiplier*1;
if(person[i].whichgun==sniperrifle)person[i].recoil-=multiplier*1;
if(person[i].whichgun==handgun1)person[i].recoil-=multiplier*2;
if(person[i].whichgun==handgun2)person[i].recoil-=multiplier*2;
if(person[i].whichgun==assaultrifle)person[i].recoil-=multiplier*10;
}
if(person[i].recoil<0)person[i].recoil=0;
if(i==0){
oldzoom = zoom;
if(zoom){
mousesensitivity=.05*usermousesensitivity;
if(person[i].targetanimation!=crouchanim||person[i].currentanimation!=crouchanim||person[i].aiming<1){
zoom=0;
}
if(visions==1)zoom=0;
}
if(person[i].currentanimation==crouchanim&&person[i].targetanimation==crouchanim&&person[i].aiming>=1&&person[i].whichgun==sniperrifle){
zoom=1;
if(zoom&&!oldzoom)camera.rotation2-=6;
}
if(!zoom)mousesensitivity=1*usermousesensitivity;
if(person[i].whichgun!=sniperrifle)zoom=0;
}
}
//Zombie eat
if(i > 0
&& person[i].targetanimation == zombieeatanim
&& person[person[i].killtarget].eaten == i) {
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].locked=1;
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].locked=1;
for(int k=0;k<2;k++){
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].position=DoRotation(person[i].skeleton.joints[person[i].skeleton.jointlabels[righthand]].position,0,person[i].playerrotation,0)+person[i].playercoords;
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].velocity=0;
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].position=DoRotation(person[i].skeleton.joints[person[i].skeleton.jointlabels[lefthand]].position,0,person[i].playerrotation,0)+person[i].playercoords;
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].velocity=0;
person[person[i].killtarget].skeleton.DoConstraints();
person[person[i].killtarget].skeleton.DoConstraints(&blocksimplecollide[citytype[person[i].whichblockx][person[i].whichblocky]],&move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
}
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[head]].locked=0;
person[person[i].killtarget].skeleton.joints[person[person[i].killtarget].skeleton.jointlabels[rightshoulder]].locked=0;
person[person[i].killtarget].longdead=1;
}
if(i>0&&enemystate!=1&&person[i].type==zombietype&&person[i].speedmult>.7){
if(findDistancefast(person[i].playercoords,person[1].playercoords)<20000)person[i].killtarget=1;
else person[i].killtarget=-1;
}
if(i>0&&enemystate!=1&&person[i].type==zombietype&&person[i].speedmult<.7){
person[i].killtarget=-1;
}
bool realcheck = false;
// Pathfinding
if (i > 0 && person[i].targetanimation != getupfrontanim
&& person[i].targetanimation != thrownanim
&& person[i].targetanimation != getupbackanim
&& person[i].currentanimation != getupfrontanim
&& person[i].currentanimation != getupbackanim) {
person[i].pathcheckdelay -= multiplier;
// Realcheck tells us
// a) we've got close to the end of our path or
// b) we're moving away from our target
auto moving_away
= findDistancefast(person[i].pathtarget,
person[i].playercoords)
> findDistancefast(person[i].pathtarget,
person[i].oldplayercoords);
realcheck = (abs(person[i].playercoords.x
- person[i].pathtarget.x) < 1
&& abs(person[i].playercoords.z
- person[i].pathtarget.z) < 1)
|| moving_away;
if(person[i].targetanimation==idleanim&&person[i].killtargetvisible==0){
person[i].targetanimation=walkanim;
if(person[i].type==zombietype)person[i].targetanimation=zombiewalkanim;
realcheck=1;
}
if((realcheck||((person[i].killtarget>-1&&person[i].type!=civiliantype)&&person[i].pathcheckdelay<=0)||person[i].killtargetvisible)){
person[i].pathcheckdelay = 1.2f;
if ((person[i].killtarget == -1
|| person[i].type == civiliantype)
&& !person[i].running) {
person[i].killtargetvisible = 0;
leastdistance = 2000000;
for (int j = 0; j < path.vertexNum; j++) {
person[i].pathtarget.x = path.vertex[j].x;
person[i].pathtarget.z = path.vertex[j].z;
person[i].pathtarget.y = path.vertex[j].y;
person[i].pathtarget *= person[i].pathsize;
person[i].pathtarget.x += person[i].whichblockx*block_spacing;
person[i].pathtarget.z += person[i].whichblocky*block_spacing;
if(findDistancefast(person[i].playercoords,person[i].pathtarget)= 0 && closesttarget < path.vertexNum) {
person[i].oldoldoldpathnum = person[i].oldoldpathnum;
person[i].oldoldpathnum = person[i].oldpathnum;
person[i].oldpathnum = person[i].pathnum;
person[i].pathnum = closesttarget;
person[i].pathtarget.x = path.vertex[person[i].pathnum].x;
person[i].pathtarget.z = path.vertex[person[i].pathnum].z;
person[i].pathtarget *= person[i].pathsize;
person[i].pathtarget.x += person[i].whichblockx*block_spacing;
person[i].pathtarget.z += person[i].whichblocky*block_spacing;
}
}
if(person[i].running&&realcheck){
person[i].killtargetvisible=0;
person[i].targetanimation=joganim;
// Dead target?
if (person[person[i].killtarget].health <= 0)
person[i].running = 0;
person[i].killtarget=1;
// If pathfind
if (realcheck) {
leastdistance = 2000000;
person[i].lastdistancevictim = 0;
closesttarget = -1;
// Check best path
closesttarget = person[i].pathnum;
// Check other blocks?
if (closesttarget == person[i].pathnum) {
beginx = person[i].whichblockx-2;
if(beginx<0)beginx=0;
beginz=person[i].whichblocky-2;
if(beginz<0)beginz=0;
endx=person[i].whichblockx+2;
if(endx>num_blocks-1)endx=num_blocks-1;
endz=person[i].whichblocky+2;
if(endz>num_blocks-1)endz=num_blocks-1;
leastdistance=2000000;
for (int l = beginx; l <= endx; l++) {
for (int m = beginx; m <= endx; m++) {
for (int j = 0; j < path.vertexNum; j++){
person[i].pathtarget.x = path.vertex[j].x;
person[i].pathtarget.y = path.vertex[j].y;
person[i].pathtarget.z = path.vertex[j].z;
person[i].pathtarget*=person[i].pathsize;
person[i].pathtarget.x+=l*block_spacing;
person[i].pathtarget.z+=m*block_spacing;
if(findDistancefast(person[i].playercoords,person[i].pathtarget)findDistancefast(person[i].playercoords,person[person[i].killtarget].playercoords)&&j!=1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[person[i].whichblockx][person[i].whichblocky])==-1&&blocksimple.LineCheck2(person[i].playercoords,person[i].pathtarget,&blah,move,cityrotation[l][m])==-1){
person[i].lastdistancevictim=findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords);
leastdistance=findDistancefast(person[i].playercoords,person[i].pathtarget);
closesttarget=j;
finaltarget=person[i].pathtarget;
person[i].whichblockx=l;
person[i].whichblocky=m;
}
}
}
}
}
if (closesttarget != -1) {
person[i].pathnum = closesttarget;
person[i].pathtarget = finaltarget;
}
}
}
// Assassin
if((person[i].killtarget>-1&&person[i].type!=civiliantype)&&!person[i].running){
// Dead target?
if(person[person[i].killtarget].health<=0&&person[i].type==eviltype){
person[i].playerrotation2 = 0;
person[i].whichgun = nogun;
person[i].targetanimation = walkanim;
person[i].lastdistancevictim = 200000;
person[i].pathnum = -1;
enemystate = 1;
person[i].killtarget = -1;
realcheck = 1;
}
if(person[i].type==zombietype&&person[person[i].killtarget].health<=0){
if(person[person[i].killtarget].eaten!=i){
person[i].playerrotation2 = 0;
person[i].targetanimation = zombiewalkanim;
person[i].lastdistancevictim = 200000;
person[i].pathnum = -1;
realcheck = 1;
person[i].killtarget = -1;
}
if(person[person[i].killtarget].eaten == i && person[i].targetanimation != zombieeatanim) {
person[i].targetanimation = zombieeatanim;
person[i].targetframe = 0;
person[i].target = 0;
}
enemystate = 1;
}
if(person[person[i].killtarget].health>0){
if(person[person[i].killtarget].skeleton.free){
person[person[i].killtarget].playercoords=person[person[i].killtarget].averageloc;
}
// If pathfind
if(realcheck){
leastdistance=2000000;
person[i].lastdistancevictim=2000000;
closesttarget=-1;
//Check best path
for(int j=0;jnum_blocks-1)endx=num_blocks-1;
endz=person[i].whichblocky+2;
if(endz>num_blocks-1)endz=num_blocks-1;
leastdistance=2000000;
for(int l=beginx;l<=endx;l++){
for(int m=beginx;m<=endx;m++){
if(l!=person[i].whichblockx||m!=person[i].whichblocky){
for(int j=0;j30000)person[i].killtargetvisible=0;
if(person[i].killtarget==0&&visions==1)person[i].killtargetvisible=0;
if(person[i].killtargetvisible){
beginx=person[i].whichblockx-2;
if(beginx<0)beginx=0;
beginz=person[i].whichblocky-2;
if(beginz<0)beginz=0;
endx=person[i].whichblockx+2;
if(endx>num_blocks-1)endx=num_blocks-1;
endz=person[i].whichblocky+2;
if(endz>num_blocks-1)endz=num_blocks-1;
for(int l=beginx;l<=endx;l++){
for(int m=beginx;m<=endx;m++){
move.x=l*block_spacing;
move.z=m*block_spacing;
move.y=-3;
if(person[i].killtargetvisible){
if(blocksimple.LineCheck2(person[i].playercoords,person[person[i].killtarget].playercoords,&blah,move,cityrotation[l][m])!=-1)
{
person[i].killtargetvisible=0;
}
}
}
}
}
if(person[i].type==eviltype){
if(!person[i].killtargetvisible&&person[i].targetanimation==idleanim){
person[i].targetanimation=joganim;
}
if(!person[i].killtargetvisible){
person[i].aiming=0;
}
if(person[i].killtargetvisible){
person[i].onpath=0;
person[i].lastdistancevictim=200000;
person[i].pathnum=-1;
if(person[i].whichgun==nogun){
person[i].whichgun=possiblegun[abs(Random()%numpossibleguns)];
person[i].reloads[person[i].whichgun]=1;
if(person[i].whichgun==knife)person[i].speedmult=.8+.5*difficulty;
}
if(person[i].aiming==0)person[i].shotdelay=shotdelayamount/difficulty;
person[i].aiming=1;
if(person[i].reloading>0)person[i].aiming=0;
if(person[i].whichgun==handgun1||person[i].whichgun==handgun2)person[i].playerrotation2=-10;
if(person[i].whichgun==assaultrifle||person[i].whichgun==sniperrifle||person[i].whichgun==shotgun)person[i].playerrotation2=20;
tooclose=1300;
toofar=3000;
if(person[i].whichgun==shotgun){
tooclose=1400;
toofar=5000;
}
if(person[i].whichgun==assaultrifle){
tooclose=5000;
toofar=9000;
}
if(person[i].whichgun==sniperrifle){
tooclose=10000;
toofar=20000;
}
if(person[i].whichgun==knife){
tooclose=20;
toofar=20000;
}
if(findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)>toofar)
person[i].targetanimation=joganim;
if((findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<=tooclose&&person[person[i].killtarget].skeleton.free==0)||(tooclose>200&&findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<=200)||(tooclose<=200&&findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)0){
if(!person[i].killtargetvisible&&person[i].targetanimation==idleanim){
person[i].targetanimation=zombiejoganim;
}
if(!person[i].killtargetvisible){
person[i].aiming=0;
}
if(person[i].killtargetvisible){
person[i].onpath=0;
person[i].lastdistancevictim=200000;
person[i].pathnum=-1;
if(person[i].aiming==0)person[i].shotdelay=shotdelayamount/difficulty;
if(findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)>20||person[i].targetanimation!=idleanim)
person[i].targetanimation=zombiejoganim;
if(findDistancefast(person[i].playercoords, person[person[i].killtarget].playercoords)<=20){
murderer=i;
person[person[i].killtarget].health=0;
person[person[i].killtarget].eaten=i;
}
finaltarget=person[person[i].killtarget].playercoords;
}
}
if(person[i].killtargetvisible||realcheck)person[i].pathtarget=finaltarget;
if(realcheck)person[i].lastdistancevictim=findDistancefast(person[i].pathtarget,person[person[i].killtarget].playercoords);
}
}
if(person[i].targetanimation!=zombieeatanim||person[i].type!=zombietype){
towards=person[i].playercoords-person[i].pathtarget;
Normalise(&towards);
person[i].playerrotation=asin(0-towards.x)*360/6.28;
if(towards.z>0)person[i].playerrotation=180-person[i].playerrotation;
}
}
}
person[i].whichblockx=((person[i].playercoords.x+block_spacing/2)/block_spacing);
person[i].whichblocky=((person[i].playercoords.z+block_spacing/2)/block_spacing);
if(!person[i].onground)person[i].velocity.y+=multiplier*gravity;
if(!person[i].onground&&(i!=0||visions!=1))person[i].playercoords+=person[i].velocity*multiplier;
//Death by bleeding/shock
if(person[i].health<=0){
person[i].skeleton.offset=0;
person[i].skeleton.free=1;
person[i].longdead=1;
for(int j=0;j0){
person[i].whichblockx=((person[i].skeleton.joints[0].position.x+block_spacing/2)/block_spacing);
person[i].whichblocky=((person[i].skeleton.joints[0].position.z+block_spacing/2)/block_spacing);
move=0;
move.x=person[i].whichblockx*block_spacing;
move.z=person[i].whichblocky*block_spacing;
person[i].skeleton.DoGravity();
if(person[i].averageloc.y<=50)person[i].skeleton.DoConstraints(&blocksimplecollide[citytype[person[i].whichblockx][person[i].whichblocky]],&move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
if(person[i].averageloc.y>50)person[i].skeleton.DoConstraints(&blockcollide[citytype[person[i].whichblockx][person[i].whichblocky]],&move,cityrotation[person[i].whichblockx][person[i].whichblocky]*90);
person[i].oldaverageloc=person[i].averageloc;
person[i].averageloc=0;
for(int j=0;j0)person[i].DrawSkeleton(i);
if(findDistancefast(person[i].averageloc,person[i].oldaverageloc)<.2*multiplier)person[i].longdead-=multiplier/2;
}
if(person[i].skeleton.free==1&&person[i].longdead<=0&&person[i].health>0&&person[i].longdead!=-1){
person[i].longdead=1;
person[i].skeleton.free=0;
person[i].currentanimation=lyinganim;
person[i].target=0;
person[i].targetframe=0;
//Get up from front or back?
if(person[i].skeleton.forward.y>0)
person[i].targetanimation=getupfrontanim;
else
person[i].targetanimation=getupbackanim;
//Find playercoords
person[i].playercoords=person[i].averageloc;
for(int j=0;jperson[i].playercoords.y)person[i].playercoords.y=person[i].skeleton.joints[j].position.y;
}
//Find orientation
XYZ firsttop=person[i].skeleton.joints[person[i].skeleton.jointlabels[neck]].position-person[i].skeleton.joints[person[i].skeleton.jointlabels[groin]].position;
Normalise(&firsttop);
person[i].playerrotation=acos(0-firsttop.z);
person[i].playerrotation*=360/6.28;
if(0>firsttop.x)person[i].playerrotation=360-person[i].playerrotation;
person[i].playerrotation*=-1;
person[i].playervelocity=0;
if(person[i].targetanimation==getupfrontanim)person[i].playerrotation+=180;
for(int j=0;j 0
&& person[0].reloading <= 0 && person[0].attackframe < 0
&& person[0].targetanimation != crouchanim
&& person[0].grenphase == 0) {
person[0].grenphase = 1;
auto soundsrc = (DoRotation(person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]].position, 0, person[0].playerrotation, 0)
+ person[0].playercoords - camera.position) / soundscalefactor;
float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[pinpullsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[pinpullsound]);
}
if (!Button() && person[0].whichgun == grenade
&& person[0].grenphase == 1) {
person[0].grenphase = 0;
person[0].attackframe = 0;
person[0].attacktarget = 0;
person[0].killtarget = 0;
}
if (person[0].targetanimation == crouchanim
&& person[0].grenphase == 1) {
person[0].grenphase = 0;
auto soundsrc = (DoRotation(person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]].position, 0, person[0].playerrotation, 0)
+ person[0].playercoords - camera.position) / soundscalefactor;
float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[pinreplacesound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[pinreplacesound]);
}
// Get gun
if (Button() && !oldbutton && person[0].currentanimation == crouchanim
&& (person[0].aiming == 0 || person[0].whichgun == grenade
|| person[0].whichgun == knife || person[0].whichgun == nogun)) {
bool switched = false;
for (int i = 1; i < max_people && !switched; i++) {
if (!person[i].skeleton.free
|| findDistancefast(person[0].playercoords,
person[i].averageloc) > 200)
continue;
auto soundsrc = (person[0].playercoords
- camera.position) / soundscalefactor;
float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[clicksound]);
auto tmp_gun = person[0].whichgun;
person[0].whichgun = person[i].whichgun;
person[i].whichgun = tmp_gun;
auto tmp_ammo = person[0].ammo;
person[0].ammo = person[i].ammo;
person[i].ammo = tmp_ammo;
switched = true;
person[0].aiming = 1;
person[0].aimamount = 0;
}
}
//Throw
if(Button()&&person[0].attackframe<0&&((person[0].whichgun==nogun||person[0].aiming==0)&&person[0].whichgun!=knife)&&person[0].currentanimation!=crouchanim&&person[0].targetanimation!=crouchanim&&person[0].targetanimation!=throwanim&&visions==0){
if(person[0].targetanimation==idleanim||person[0].targetanimation==walkanim){
bool attacking=0;
person[0].killtarget=-1;
float closedistance=-1;
for(int i=1;i1||(person[0].attackframe>=0&&person[0].currentanimation==joganim)){
if(person[person[0].killtarget].skeleton.free<1&&person[0].killtarget!=0&&(person[0].aiming<1||person[0].whichgun==nogun||person[0].whichgun==knife||person[0].targetanimation==joganim)){
auto soundpos = person[0].playercoords + flatfacing
- camera.position;
float gLoc[] {
soundpos.x / 2 / soundscalefactor,
soundpos.y / 2 / soundscalefactor,
soundpos.z / 2 / soundscalefactor,
};
if (person[person[0].killtarget].type != zombietype) {
if (person[0].whichgun != knife) {
alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[headwhacksound]);
} else {
alSourcefv(gSourceID[knifeslashsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[knifeslashsound]);
person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]];
person[person[0].killtarget].bleeding=1;
person[person[0].killtarget].bleeddelay=1;
person[0].bjoint1=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
person[0].bjoint2=&person[0].skeleton.joints[person[0].skeleton.jointlabels[righthand]];
person[0].bleeding=1;
person[0].bleeddelay=1;
velocity=DoRotation(flatfacing,0,70,0)*50+person[0].velocity*2;
velocity.y+=30;
sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.3, 2);
sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.2, 3);
sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,DoRotation(person[person[0].killtarget].skeleton.joints[person[person[0].killtarget].skeleton.jointlabels[neck]].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.1, 4);
}
person[person[0].killtarget].health-=100;
person[person[0].killtarget].skeleton.free=1;
person[person[0].killtarget].longdead=1;
for(int j=0;j 0
|| findDistancefast(person[i].playercoords,
person[0].playercoords
+ flatfacing) > 22)
continue;
float gLoc[] {
flatfacing.x / soundscalefactor / 2,
flatfacing.y / soundscalefactor / 2,
flatfacing.z / soundscalefactor / 2,
};
alSourcefv(gSourceID[headwhacksound],
AL_POSITION, gLoc);
alSourcePlay(gSourceID[headwhacksound]);
person[i].skeleton.free = 1;
person[i].longdead = 1;
for (auto& joint : person[i].skeleton.joints) {
joint.position = DoRotation(joint.position, 0, person[i].playerrotation, 0);
joint.position += person[i].playercoords;
joint.realoldposition = joint.position;
joint.velocity = person[0].velocity;
joint.velocity.y = -10;
joint.velocity.x += abs(Random() % 10) - 5;
joint.velocity.y += abs(Random() % 10) - 5;
joint.velocity.z += abs(Random() % 10) - 5;
}
}
}
// Fire/wing
bool firing = false;
if (!Button()) {
oldbutton = 0;
} else if (oldbutton) {
} else if (person[0].ammo <= 0 && person[0].aiming
&& person[0].targetanimation != joganim
&& person[0].whichgun != nogun
&& person[0].whichgun != knife
&& person[0].whichgun != grenade) {
auto& coords = person[0].playercoords;
float gLoc[] {
coords.x / soundscalefactor,
coords.y / soundscalefactor,
coords.z / soundscalefactor,
};
alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[clicksound]);
oldbutton = 1;
} else if (visions == 1) {
alSourcePlay(gSourceID[soulinsound]);
} else {
firing = true;
// Assault rifles are automatic.
if (person[0].whichgun != assaultrifle)
oldbutton = 1;
}
XYZ wallhit;
XYZ start;
XYZ finalwallhit;
int numshots;
XYZ hitnorm;
XYZ hitmove;
int hitpoly = 0;
float hitrotation = 0.0f;
Model* model = NULL;
for (int j = 0; j < numpeople; j++) {
if (j && person[j].type != eviltype)
continue;
if (person[j].ammo <= 0
|| person[j].reloading > 0
|| person[j].targetanimation == joganim
|| person[j].aimamount < 1)
firing = false;
else if (j)
firing = person[j].whichgun != nogun
&& person[j].whichgun != knife
&& person[j].killtargetvisible
&& person[j].shotdelay < 0;
if (j && person[j].killtargetvisible
&& person[j].whichgun != nogun
&& person[j].whichgun != knife) {
person[j].aiming = 1;
if (person[j].shotdelay > 0)
person[j].shotdelay -= multiplier * 0.9;
}
if (person[j].skeleton.free == 1
|| person[j].targetanimation == getupfrontanim
|| person[j].targetanimation == getupbackanim)
person[j].shotdelay = shotdelayamount
/ difficulty;
if (person[j].ammo == 0
&& person[j].reloads[person[j].whichgun] > 0) {
person[j].ammo = -1;
person[j].aiming = 0;
}
if (!firing || person[j].aiming < 1 || person[j].recoil > 0)
continue;
person[j].shotdelay = shotdelayamount / difficulty;
HitStruct hitstruct, temphitstruct;
person[j].litup = 1;
person[j].recoil = 1;
float olddistance = 0.0f, distance = 0.0f;
float totalarea = 0.0f;
int whichhit = -1;
numshots = (person[j].whichgun == shotgun) ? 7 : 1;
if (person[j].whichgun != grenade)
person[j].ammo--;
for (int p = 0; p < numshots; p++) {
XYZ aim;
if (j)
aim = aimBot(j);
else if (!zoom)
aim = aimPlayer();
else
aim = facing;
Normalise(&aim);
int aimjoint;
switch (person[j].whichgun) {
case handgun1:
case handgun2:
aimjoint = person[j].skeleton.jointlabels[rightwrist];
break;
default:
aimjoint = person[j].skeleton.jointlabels[lefthand];
}
start = person[j].playercoords
+ DoRotation(person[j].skeleton.joints[aimjoint].position,
0, person[j].playerrotation, 0);
auto startsub = DoRotation(aim,
0, -person[j].playerrotation, 0);
startsub = DoRotation(startsub, 90, 0, 0);
startsub *= DoRotation(startsub,
0, person[j].playerrotation,0);
switch (person[j].whichgun) {
case sniperrifle:
case shotgun:
start -= startsub * 0.35f;
break;
case handgun1:
case handgun2:
start -= startsub * 0.55f;
break;
default: // assaultrifle
start -= startsub * 0.25f;
}
if (p == numshots - 1) {
auto crouch = person[j].currentanimation == crouchanim;
float rot = 0.0f, rot2 = 0.0f;
switch (person[j].whichgun) {
case sniperrifle:
case shotgun:
rot2 = crouch ? 3.0f : 7.0f;
break;
case handgun1:
rot2 = crouch ? 4.0f : 6.0f;
break;
case handgun2:
rot2 = crouch ? 3.0f : 5.0f;
break;
case assaultrifle:
rot = Random() % 100 / (crouch ? 60.0f : 50.0f);
rot2 = crouch ? 1.5f : 2.3f;
break;
}
camera.rotation -= rot;
camera.rotation2 -= rot2;
auto soundpos = start - camera.position;
ALfloat gLoc[] {
soundpos.x / 4 / soundscalefactor,
soundpos.y / 4 / soundscalefactor,
soundpos.z / 4 / soundscalefactor,
};
ALuint gunsound;
switch (person[j].whichgun) {
case sniperrifle:
gunsound = gSourceID[riflesound];
break;
case shotgun:
gunsound = gSourceID[shotgunsound];
break;
case handgun1:
gunsound = gSourceID[pistol1sound];
break;
case handgun2:
gunsound = gSourceID[pistol2sound];
break;
default: // assaultrifle
gunsound = gSourceID[machinegunsound];
}
alSourcefv(gunsound, AL_POSITION, gLoc);
alSourcePlay(gunsound);
}
XYZ end {start + aim * 1000};
if (debug && j == 0 && IsKeyDown(GLFW_KEY_G)) {
sprites.MakeSprite(grenadesprite, 1, 1, 1, 1,
start, aim * 200, 1.01);
continue;
}
int bulletstrength=1;
int firstpass=-1;
bool penetrate;
for(int m=0;mnum_blocks-1)endx=num_blocks-1;
endz=(person[j].playercoords.z+block_spacing/2)/block_spacing+3;
if(endz>num_blocks-1)endz=num_blocks-1;
if(beginx.9)bulletstrength=2;
}
}
wallhit=0;
wallhit.x=camera.position.x;
wallhit.z=camera.position.z;
whichtri=Bigstreet.LineCheck2(start,end,&wallhit,wallhit,0);
if(whichtri!=-1){
end.y-=.5;
end=wallhit;
finalwallhit=wallhit;
bulletstrength=2;
hitnorm=0;
hitnorm.y=1;
hitmove=0;
hitrotation=0;
}
if(m==0){
if(j==0&&slomo==2){
soundscalefactor=soundscalefactordefault;
alSourceStop(gSourceID[whichsong]);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
if(person[0].whichgun==knife)whichsong=knifesong;
if(person[0].whichgun!=knife)whichsong=shootsong;
if(type==zombie_type)whichsong=zombiesong;
alSourcef(gSourceID[whichsong], AL_PITCH, 1);
alSourcePlay(gSourceID[whichsong]);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
slomo=0;
if(whichhit==-1)alSourcePlay(gSourceID[disguisekillsound]);
flashamount=.5;
flashr=1;flashg=1;flashb=1;
}
}
//Impact
XYZ oldend {end};
//with person
if(whichhit!=-1&&whichhit!=firstpass){
if(j==0)person[whichhit].dead=1;
if(whichhit==1){
murderer=j;
}
if(person[whichhit].health==100&&j==0){
if(person[whichhit].type==civiliantype)civkills++;
if(person[whichhit].type==eviltype)goodkills++;
}
if(person[whichhit].health==100&&j!=0){
badkills++;
}
//penetrate
penetrate=abs(Random()%2)==1;
if(numshots>1)penetrate=0;
if(penetrate){bulletstrength=2;
firstpass=whichhit;
end=start+aim*1000;}
if(person[j].whichgun==assaultrifle)person[whichhit].health-=20;
if(person[j].whichgun==assaultrifle&&person[whichhit].type==zombietype)person[whichhit].health-=60;
if(person[j].whichgun==handgun1){
if(person[whichhit].type!=zombietype)person[whichhit].health-=100;
if(person[whichhit].type==zombietype)person[whichhit].health-=100;
person[whichhit].DoAnimations(whichhit);
}
if(person[j].whichgun==handgun2)person[whichhit].health-=20;
if(person[j].whichgun==handgun2&&person[whichhit].type==zombietype)person[whichhit].health-=60;
if(person[j].whichgun==sniperrifle&&m!=0)person[whichhit].health-=30;
if(person[j].whichgun==shotgun)person[whichhit].health-=60;
if(person[j].whichgun==sniperrifle&&m==0){
if(person[whichhit].type!=zombietype)person[whichhit].health-=100;
if(person[whichhit].type==zombietype)person[whichhit].health-=120;
person[whichhit].DoAnimations(whichhit);
}
if(hitstruct.joint1->modelnum==headmodel&&person[whichhit].type!=zombietype){
person[whichhit].health-=60;
}
if(person[whichhit].type==zombietype)person[whichhit].speedmult-=.05;
if(person[whichhit].type==zombietype)person[whichhit].maxhealth-=10;
if (whichhit == 0) {
bulletstrength = 1;
person[0].health = 100;
flashamount = 1;
flashr = flashg = flashb = 0;
auto soundsrc = (hitstruct.hitlocation - camera.position) / soundscalefactor;
float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[bodywhacksound]);
}
person[whichhit].longdead=1;
if(person[whichhit].health<=0){
person[whichhit].skeleton.offset=0;
if(person[whichhit].skeleton.free!=1){
person[whichhit].skeleton.free=1;
totalarea=0;
for(int j=0;j0){
if (person[whichhit].killtargetvisible == 0
&& person[whichhit].type != zombietype
&& person[whichhit].currentanimation !=getupfrontanim
&& person[whichhit].currentanimation != getupbackanim) {
if(hitstruct.joint1->modelnum==headmodel)person[whichhit].targetanimation=headpainanim;
if(hitstruct.joint1->modelnum==chestmodel)person[whichhit].targetanimation=chestpainanim;
if(hitstruct.joint1->modelnum==abdomenmodel)person[whichhit].targetanimation=stomachpainanim;
if(hitstruct.joint1->label==rightelbow||hitstruct.joint1->label==rightshoulder||hitstruct.joint1->label==rightwrist||hitstruct.joint1->label==righthand)person[whichhit].targetanimation=rightarmpainanim;
if(hitstruct.joint1->label==leftelbow||hitstruct.joint1->label==leftshoulder||hitstruct.joint1->label==leftwrist||hitstruct.joint1->label==lefthand)person[whichhit].targetanimation=leftarmpainanim;
if(hitstruct.joint1->label==rightknee||hitstruct.joint1->label==righthip||hitstruct.joint1->label==rightankle||hitstruct.joint1->label==rightfoot)person[whichhit].targetanimation=rightlegpainanim;
if(hitstruct.joint1->label==leftknee||hitstruct.joint1->label==lefthip||hitstruct.joint1->label==leftankle||hitstruct.joint1->label==leftfoot)person[whichhit].targetanimation=leftlegpainanim;
person[whichhit].targetframe=0;
person[whichhit].target=0;
}
person[whichhit].skeleton.offset=1;
for(int j=0;j36){
Normalise(&person[whichhit].skeleton.joints[j].offset);
person[whichhit].skeleton.joints[j].offset*=6;
}
}
}
if(hitstruct.joint1->modelnum==headmodel&&person[whichhit].health<=0){
for(int j=0;jmodelnum != headmodel) {
if(person[j].whichgun==sniperrifle)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 5);
if(person[j].whichgun==sniperrifle&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 7);
if(person[j].whichgun==shotgun)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 5);
if(person[j].whichgun==shotgun&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 7);
if(person[j].whichgun==assaultrifle)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 3);
if(person[j].whichgun==assaultrifle&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 7);
if(person[j].whichgun==handgun1)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 3);
if(person[j].whichgun==handgun1&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 4);
if(person[j].whichgun==handgun2)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*0, 3);
if(person[j].whichgun==handgun2&&penetrate)sprites.MakeSprite(bloodspritenoup, 1, 1, 0, 0, hitstruct.hitlocation, velocity*-3, 4);
}else{
sprites.MakeSprite(bloodspritenoup, 1, 1, .2, .2, hitstruct.hitlocation, velocity*0, 6);
sprites.MakeSprite(bloodspritenoup, 1, 1, .5, .5, hitstruct.hitlocation, velocity*-2, 7);
sprites.MakeSprite(bloodspritenoup, 1, 1, .2, .2, hitstruct.hitlocation, velocity*-3, 10);
}
person[whichhit].bjoint1=hitstruct.joint1;
person[whichhit].bjoint2=hitstruct.joint2;
person[whichhit].bleeding=1;
person[whichhit].bleeddelay=1;
auto hitsound = (hitstruct.joint1->modelnum == headmodel)
? gSourceID[headshotsound]
: gSourceID[bodyhitsound];
auto hitpos = hitstruct.hitlocation
- camera.position;
ALfloat gLoc[] {
hitpos.x / soundscalefactor / 4,
hitpos.y / soundscalefactor / 4,
hitpos.z / soundscalefactor / 4,
};
ALfloat gain = thirdperson ? 0.1f : 1.0f;
alSourcef(hitsound, AL_MIN_GAIN, gain);
alSourcefv(hitsound, AL_POSITION, gLoc);
alSourcePlay(hitsound);
}//with wall
if(oldend==finalwallhit){
decals.MakeDecal(bullethole, finalwallhit,.7,hitnorm, hitpoly, model, hitmove, hitrotation);
XYZ velocity;
velocity=aim*-4;
velocity=hitnorm*3;
if(person[j].whichgun==sniperrifle){
sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 10);
sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 2);
}
if(person[j].whichgun==shotgun){
sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 5);
sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, .8);
}
if(person[j].whichgun==assaultrifle){
sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
}
if(person[j].whichgun==handgun1){
sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
}
if(person[j].whichgun==handgun2){
sprites.MakeSprite(smokesprite, .4, 1, 1, 1, finalwallhit, velocity, 6);
sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, finalwallhit, velocity, 1);
}
auto wallhitpos = finalwallhit
- camera.position;
ALfloat gLoc[] {
wallhitpos.x / soundscalefactor,
wallhitpos.y / soundscalefactor,
wallhitpos.z / soundscalefactor,
};
alSourcefv(gSourceID[wallhitsound],
AL_POSITION, gLoc);
alSourcePlay(gSourceID[wallhitsound]);
}
lastshot[0]=start;
lastshot[1]=oldend;
velocity=aim*8;
if(person[j].whichgun!=sniperrifle&&person[j].whichgun!=shotgun&&p==numshots-1)sprites.MakeSprite(smokesprite, .3, 1, 1, 1, start+aim*1.5, velocity, 3);
if(person[j].whichgun==shotgun&&p==numshots-1)sprites.MakeSprite(smokesprite, .4, 1, 1, 1, start+aim*1.5, velocity, 5);
if(person[j].whichgun==sniperrifle&&!zoom)sprites.MakeSprite(smokesprite, .3, 1, 1, 1, start+aim*2.2, velocity, 4);
if(j!=0||zoom==0)sprites.MakeSprite(bullet, .07, 1, 1, .7, lastshot[0]+aim*1, lastshot[1], .2);
//Nearby bullet whoosh
long dot_ta,dot_tb;
XYZ *a,*b,*c,nearest;
a=&lastshot[0];
*a+=aim*1;
b=&lastshot[1];
c=&camera.position;
nearest=0;
dot_ta = (c->x - a->x)*(b->x - a->x) + (c->y - a->y)*(b->y - a->y) + (c->z - a->z)*(b->z - a->z);
dot_tb = (c->x - b->x)*(a->x - b->x) + (c->y - b->y)*(a->y - b->y) + (c->z - b->z)*(a->z - b->z);
if (dot_ta > 0 && dot_tb > 0) {
nearest.x = a->x + ((b->x - a->x) * dot_ta) / (dot_ta + dot_tb);
nearest.y = a->y + ((b->y - a->y) * dot_ta) / (dot_ta + dot_tb);
nearest.z = a->z + ((b->z - a->z) * dot_ta) / (dot_ta + dot_tb);
}
if (nearest.x
&& findDistancefast(nearest, camera.position) < 10
&& (thirdperson == 2 || j != 0)) {
auto nearsound = nearest - camera.position;
ALfloat gLoc[] {
nearsound.x / soundscalefactor,
nearsound.y / soundscalefactor,
nearsound.z / soundscalefactor,
};
alSourcefv(gSourceID[nearbulletsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[nearbulletsound]);
}
}
}
}
if(lasersight&&person[0].whichgun!=grenade){
for(int j=0;j=1){
//Firing
XYZ end, aim;
HitStruct hitstruct,temphitstruct;
float olddistance = 0.0f;
float distance;
int whichhit=-1;
if(!zoom||j!=0){
if(person[j].whichgun==assaultrifle)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation-2.5,0);
if(person[j].whichgun==sniperrifle)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation+4,0);
if(person[j].whichgun==shotgun)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position-person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position,0,person[j].playerrotation+4,0);
if(person[j].whichgun==handgun1&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.65+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.35),0,person[j].playerrotation-.9,0);
if(person[j].whichgun==handgun1&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.35+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.65),0,person[j].playerrotation-.9,0);
if(person[j].whichgun==handgun2&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.65+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.35),0,person[j].playerrotation-.9,0);
if(person[j].whichgun==handgun2&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[righthand])].position-(person[j].skeleton.joints[person[j].skeleton.jointlabels[head]].position*.35+person[j].skeleton.joints[person[j].skeleton.jointlabels[neck]].position*.65),0,person[j].playerrotation-.9,0);
}
if(zoom&&j==0){
start=camera.position;
aim=facing;
}
Normalise(&aim);
if(person[j].whichgun==sniperrifle){
start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(0-.4);
}
if(person[j].whichgun==shotgun){
start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(0-.4);
}
if(person[j].whichgun==handgun1){
start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[rightwrist])].position,0,person[j].playerrotation,0);
start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(.55-.4);
}
if(person[j].whichgun==handgun2){
start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[rightwrist])].position,0,person[j].playerrotation,0);
start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(.55-.4);
}
if(person[j].whichgun==assaultrifle){
start=person[j].playercoords+DoRotation(person[j].skeleton.joints[(person[j].skeleton.jointlabels[lefthand])].position,0,person[j].playerrotation,0);
start-=DoRotation(DoRotation(DoRotation(aim,0,-person[j].playerrotation,0),90,0,0),0,person[j].playerrotation,0)*(.25-.4);
}
end=start+aim*1000;
//Blocks
wallhit=0;
beginx=(person[j].playercoords.x+block_spacing/2)/block_spacing-2;
if(beginx<0)beginx=0;
beginz=(person[j].playercoords.z+block_spacing/2)/block_spacing-2;
if(beginz<0)beginz=0;
endx=(person[j].playercoords.x+block_spacing/2)/block_spacing+2;
if(endx>num_blocks-1)endx=num_blocks-1;
endz=(person[j].playercoords.z+block_spacing/2)/block_spacing+2;
if(endz>num_blocks-1)endz=num_blocks-1;
if(beginx0){
wherex=(sprites.location[i].x+block_spacing/2)/block_spacing;
wherey=(sprites.location[i].z+block_spacing/2)/block_spacing;
move=0;
move.x=wherex*block_spacing;
move.z=wherey*block_spacing;
whichtri=blocks[citytype[wherex][wherey]].LineCheck2(sprites.oldlocation[i],sprites.location[i],&wallhit,move,cityrotation[wherex][wherey]*90);
if(whichtri!=-1){
impact=1;
normalrotated=DoRotation(blocks[citytype[wherex][wherey]].normals[whichtri],0,cityrotation[wherex][wherey]*90,0);
if(sprites.size[i]>1)decals.MakeDecal(crater, wallhit,9,normalrotated, whichtri, &blocks[citytype[wherex][wherey]], move, cityrotation[wherex][wherey]*90);
sprites.location[i]=wallhit+normalrotated*.02;
ReflectVector(&sprites.velocity[i],&normalrotated);
sprites.velocity[i]*=.3;
if (sprites.type[i] == grenadesprite
&& sprites.size[i] <= 1) {
auto soundpos = sprites.location[i] - camera.position;
auto v = findLengthfast(sprites.velocity[i]) * 0.2f;
ALfloat gLoc[] {
soundpos.x / v / soundscalefactor,
soundpos.y / v / soundscalefactor,
soundpos.z / v / soundscalefactor,
};
whichsound = bouncesound + abs(Random()%2);
alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[whichsound]);
}
if(findLengthfast(sprites.velocity[i])<=10)sprites.velocity[i]=0;
}
if(sprites.location[i].y<0){
impact=1;
sprites.velocity[i].y*=-1;
sprites.velocity[i]*=.3;
sprites.location[i].y=0;
if(sprites.type[i]==grenadesprite){
if(sprites.size[i]>1){
move=0;
sprites.location[i].y=-.5;
XYZ normish;
normish=0;
normish.y=1;
decals.MakeDecal(crater, sprites.location[i],9,normish, 0, &blocks[citytype[wherex][wherey]], move, 0);
}
auto soundpos = sprites.location[i] - camera.position;
auto v = findLengthfast(sprites.velocity[i]) * 0.2f;
ALfloat gLoc[] {
soundpos.x / v / soundscalefactor,
soundpos.y / v / soundscalefactor,
soundpos.z / v / soundscalefactor,
};
whichsound = bouncesound + abs(Random()%2);
alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc);
if (sprites.size[i] <= 1)
alSourcePlay(gSourceID[whichsound]);
}
if(findLengthfast(sprites.velocity[i])<=10)sprites.velocity[i]=0;
}
if(sprites.type[i]==grenadesprite&&findLengthfast(sprites.velocity[i])>20){
HitStruct hitstruct;
for(int j=0;jlabel==head||hitstruct.joint2->label==head)&&person[j].type!=zombietype){
alSourcefv(gSourceID[headwhacksound], AL_POSITION, gLoc);
if(sprites.size[i]<=1)alSourcePlay(gSourceID[headwhacksound]);
person[j].skeleton.free=1;
person[j].longdead=1;
for (int k = 0; k < person[j].skeleton.num_joints; ++k) {
person[j].skeleton.joints[k].realoldposition
= person[j].skeleton.joints[k].position
= DoRotation(person[j].skeleton.joints[k].position,
0, person[j].playerrotation, 0)
+ person[j].playercoords;
person[j].skeleton.joints[k].velocity = person[j].velocity;
person[j].skeleton.joints[k].velocity.x += abs(Random()%10)-5;
person[j].skeleton.joints[k].velocity.y += abs(Random()%10)-5;
person[j].skeleton.joints[k].velocity.z += abs(Random()%10)-5;
}
hitstruct.joint1->velocity += sprites.velocity[i];
hitstruct.joint2->velocity += sprites.velocity[i];
if (person[j].type == civiliantype)
civkills++;
if (person[j].type == eviltype)
goodkills++;
} else {
float totalarea = 0.0f;
alSourcefv(gSourceID[bodywhacksound], AL_POSITION, gLoc);
if(sprites.size[i]<=1)alSourcePlay(gSourceID[bodywhacksound]);
person[j].skeleton.offset=1;
for(int k=0;k9){
Normalise(&person[j].skeleton.joints[k].offset);
person[j].skeleton.joints[k].offset*=3;
}
}
}}
sprites.velocity[i]*=-.3;
}
}
}
}
sprites.oldlocation[i]=sprites.location[i];
}
//Explode
if(sprites.type[i]==grenadesprite){
sprites.brightness[i]-=multiplier*.3;
if(sprites.brightness[i]<=0||(impact&&sprites.size[i]>1)){
sprites.brightness[i]=0;
sprites.MakeSprite(smokesprite, 1, 1, 1, 1, sprites.location[i], facing*0, 60);
sprites.MakeSprite(muzzleflashsprite, 1, 1, 1, 1, sprites.location[i], facing*0, 9);
auto explodepos = sprites.location[i]
- camera.position;
ALfloat gLoc[] {
explodepos.x / 3 / soundscalefactor,
explodepos.y / 3 / soundscalefactor,
explodepos.z / 3 / soundscalefactor,
};
alSourcefv(gSourceID[explosionsound], AL_POSITION, gLoc);
alSourcePlay(gSourceID[explosionsound]);
XYZ relation;
camerashake=1-findDistance(person[0].playercoords,sprites.location[i])/200;
//if(!sprites.size[i]>1){
overpoint=sprites.location[i];
overpoint.y+=3000;
underpoint=sprites.location[i];
underpoint.y-=3000;
move=0;
wherex=(sprites.location[i].x+block_spacing/2)/block_spacing;
wherey=(sprites.location[i].z+block_spacing/2)/block_spacing;
move.x=wherex*block_spacing;
move.z=wherey*block_spacing;
XYZ temp;
whichtri=sidewalkcollide.LineCheck2(overpoint,underpoint,&temp,move,cityrotation[wherex][wherey]*90);
XYZ normish;
normish=0;
normish.y=1;
if(whichtri>=0){
decals.MakeDecal(crater, sprites.location[i],9,normish, 0, &sidewalkcollide, move, cityrotation[wherex][wherey]*90);
}
if(whichtri==-1){
temp=sprites.location[i];
temp.y=-.5;
move=0;
decals.MakeDecal(crater, sprites.location[i],9,normish, 0, &sidewalkcollide, move, 0);
}
//}
for(int k=0;k=1)){
if(person[k].skeleton.free!=1){
if(person[k].type==civiliantype)civkills++;
if(person[k].type==eviltype)goodkills++;
person[k].skeleton.free=1;
person[k].killtargetvisible=0;
if((findDistancefast(person[k].playercoords,sprites.location[i])<600&&person[k].skeleton.free<1)||(findDistancefast(person[k].averageloc,sprites.location[i])<600&&person[k].skeleton.free>=1)||person[k].type==playertype){
person[k].health-=100;
person[k].bleeding=1;
}
person[k].DoAnimations(k);
person[k].longdead = 1;
person[k].bleeddelay = 1;
person[k].bjoint1 = &person[k].skeleton.joints[person[k].skeleton.jointlabels[head]];
person[k].bjoint2 = &person[k].skeleton.joints[person[k].skeleton.jointlabels[neck]];
for(int j=0;j1)person[k].skeleton.joints[j].velocity+=relation/findDistance(person[k].skeleton.joints[j].position,sprites.location[i])*300;
else person[k].skeleton.joints[j].velocity+=relation*300;
}
person[k].longdead=1;
for(int j=0;j1500&&person[k].skeleton.joints[j].existing==1&&abs(Random()%3)!=1){
sprites.MakeSprite(bloodspritedown, .8, 1, .2, .2,person[k].skeleton.joints[j].position, person[k].skeleton.joints[j].velocity/3, 9);
person[k].skeleton.DeleteJoint(j);
person[k].skeleton.broken=2;
person[k].health=-10000;
person[k].skeleton.joints[j].existing=0;
}
}
}
}
}
}
}
}
}
//camera shake
camerashake-=multiplier;
if(camerashake<0)camerashake=0;
//camera position
XYZ average;
if(!zoom)average=person[0].skeleton.joints[(person[0].skeleton.jointlabels[head])].position*(person[0].aimamount/2+.5)+person[0].skeleton.joints[(person[0].skeleton.jointlabels[neck])].position*((1-person[0].aimamount)/2);
if(zoom)average=person[0].skeleton.joints[(person[0].skeleton.jointlabels[righthand])].position;
if(person[0].skeleton.free==0&&thirdperson!=2)camera.position=person[0].playercoords+DoRotation(average,0,person[0].playerrotation,0);
if(person[0].skeleton.free==1&&thirdperson!=2)camera.position=average;
//Restraints
if(camera.position.y<.1)camera.position.y=.1;
if(thirdperson!=2){
oldrot=camera.visrotation;
oldrot2=camera.visrotation2;
}
//Kill count
for(int i=0;i0&&person[i].health<=0){
if(i==1)alSourcePlay(gSourceID[losesound]);
if(person[i].type==civiliantype){
alSourcePlay(gSourceID[disguisekillsound]);
score-=300;
}
if(person[i].type==eviltype){
alSourcePlay(gSourceID[soulinsound]);
score+=75;
if(person[i].whichgun==knife)score+=50;
}
person[i].firstlongdead=0;
}
person[i].oldhealth=person[i].health;
}
if(slomo==2){
psychicpower-=multiplier*15;
if(psychicpower<0){
soundscalefactor=soundscalefactordefault;
alSourceStop(gSourceID[whichsong]);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 0);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 0);
if(person[0].whichgun==knife)whichsong=knifesong;
if(person[0].whichgun!=knife)whichsong=shootsong;
if(type==zombie_type)whichsong=zombiesong;
alSourcef(gSourceID[whichsong], AL_PITCH, 1);
alSourcePlay(gSourceID[whichsong]);
alSourcef(gSourceID[whichsong], AL_MIN_GAIN, 1);
alSourcef(gSourceID[whichsong], AL_MAX_GAIN, 1);
slomo=0;
alSourcePlay(gSourceID[soulinsound]);
psychicpower=0;
flashamount=.5;
flashr=1;flashg=1;flashb=1;
}
}
psychicpower+=multiplier*5;
if(psychicpower>10)psychicpower=10;
if (paused || person[0].currentanimation== diveanim
|| person[0].currentanimation == throwanim)
GetMouse(&mouseloc);
setListener(facing);
if (score < 0)
score = 0;
}