// 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 #include "Game.h" #include "misc.h" extern float multiplier; extern int thirdperson; extern int visions; extern Sprites sprites; extern unsigned int gSourceID[37]; 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 Decals decals; #define maxfallvel 40 void Splat(Game* game, int k) { if (k && visions) return; auto& person = game->person[k]; if (person.velocity.y > -maxfallvel) { person.velocity.y = 0; return; } auto& skeleton = person.skeleton; skeleton.free = 1; skeleton.offset = 0; person.health = 0; person.longdead = person.bleeding = person.bleeddelay = 1; person.DoAnimations(k); auto& joints = skeleton.joints; auto& head_joint = joints[head]; person.bjoint1 = &head_joint; person.bjoint2 = joints + neck; for (auto& joint : joints) { joint.position = DoRotation(joint.position + joint.offset, 0, person.playerrotation, 0) + person.playercoords; joint.realoldposition = joint.position; joint.velocity = {0, person.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 updateSong(Game* game) { if (environment == rainy_environment) alSourcePlay(gSourceID[rainsound]); else alSourcePause(gSourceID[rainsound]); alSourceStop(gSourceID[game->whichsong]); alSourcef(gSourceID[game->whichsong], AL_MIN_GAIN, 0); alSourcef(gSourceID[game->whichsong], AL_MAX_GAIN, 0); if (game->type == zombie_type) game->whichsong = zombiesong; else if (game->person[0].whichgun == knife) game->whichsong = knifesong; else game->whichsong = shootsong; alSourcef(gSourceID[game->whichsong], AL_PITCH, 1); alSourcef(gSourceID[game->whichsong], AL_MIN_GAIN, 1); alSourcef(gSourceID[game->whichsong], AL_MAX_GAIN, 1); alSourcePlay(gSourceID[game->whichsong]); } void click(Game* game, int button, int action, int mods) { if (game->menu) { if (button != GLFW_MOUSE_BUTTON_LEFT) return; double xpos, ypos; auto window = glfwGetCurrentContext(); glfwGetCursorPos(window, &xpos, &ypos); double mousex = xpos * 640 / game->screenwidth; double mousey = 480 - ypos * 480 / game->screenheight; auto button = 0; if (mousex > 120 && mousex < 560) { if (mousey > 235 && mousey < 305) button = 1; else if (mousey > 112 && mousey < 182) button = 2; } if (action == GLFW_PRESS) { game->mouseoverbutton = button; return; } else if (button != game->mouseoverbutton) { game->mouseoverbutton = 0; } switch (game->mouseoverbutton) { case 1: updateSong(game); game->flashr = game->flashg = game->flashb = 1.0f; game->flashamount = 1.0f; alSourcePlay(gSourceID[soulinsound]); if (!game->gameinprogress) { game->mission = 0; initGame(game); } if (visions) alSourcePlay(gSourceID[visionsound]); game->gameinprogress = true; setMenu(game, false); break; case 2: if (game->gameinprogress) { game->flashr = game->flashg = game->flashb = 1.0f; game->flashamount = 1.0f; game->gameinprogress = false; } else { game->flashamount = game->flashr = 1.0f; game->flashg = game->flashb = 0.0f; glfwSetWindowShouldClose(window, true); } alSourcePlay(gSourceID[losesound]); break; } game->mouseoverbutton = 0; return; } auto& player = game->person[0]; auto& weapon = player.whichgun; if (visions) { if (action == GLFW_PRESS) alSourcePlay(gSourceID[soulinsound]); return; } 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); // Gun whacking or knife slashing if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS && player.attackframe < 0 && (!player.aiming || player.ammo <= 0 || weapon == nogun || weapon == knife || player.targetanimation == joganim) && player.targetanimation != diveanim && player.targetanimation != throwanim) { bool attacking = false; float closedistance = 0.0f; for (int i = 1; i < game->numpeople; ++i) { auto& person = game->person[i]; if (person.type == viptype || person.skeleton.free) continue; auto distance = findDistancefast(person.playercoords, player.playercoords + flatfacing); if (distance > 12 + (weapon == knife) * 10) continue; if (closedistance == 0 || distance < closedistance) { attacking = true; player.killtarget = i; closedistance = distance; } } if (attacking) { player.attacktarget = 0; player.attackframe = 0; game->whacked = false; return; } } // Disarming if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS && player.attackframe < 0 && (!player.aiming || weapon == nogun || weapon == knife) && (player.targetanimation == idleanim || player.targetanimation == walkanim || player.targetanimation == joganim)) { bool attacking = false; float closedistance = 0.0f; for (int i = 1; i < game->numpeople; ++i) { auto& person = game->person[i]; if (person.skeleton.free || person.whichgun == nogun) continue; auto distance = findDistancefast(person.playercoords, player.playercoords + flatfacing); if (distance > 12) continue; attacking = true; if (closedistance == 0 || distance < closedistance) { player.killtarget = i; closedistance = distance; } } if (attacking) { auto& target = game->person[player.killtarget]; weapon = target.whichgun; player.ammo = target.ammo; player.aiming = true; target.whichgun = nogun; target.killtarget = -1; target.targetframe = player.targetframe = 0; target.targetanimation = player.targetanimation = throwanim; target.target = player.target = 1; target.playercoords = player.playercoords; target.playerrotation = player.playerrotation; target.speed = player.speed = 1; target.speedmult = 1; game->score += 150; return; } } // Pulling gun trigger if (player.aiming && player.targetanimation != joganim && weapon != nogun && weapon != knife && weapon != grenade) { if (button == GLFW_MOUSE_BUTTON_RIGHT && weapon == sniperrifle) game->zoom = action == GLFW_PRESS; else if (button == GLFW_MOUSE_BUTTON_LEFT) player.firing = action == GLFW_PRESS; else if (button == GLFW_MOUSE_BUTTON_MIDDLE && game->debug) player.firing = player.grenphase = action == GLFW_PRESS; return; } // Grenade if (weapon == grenade && player.ammo > 0 && player.reloading <= 0 && player.attackframe < 0) { auto& skeleton = player.skeleton; auto& hand = skeleton.joints[righthand]; auto soundsrc = DoRotation(hand.position, 0, player.playerrotation, 0) + player.playercoords - camera.position; if (player.grenphase) { if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) { // throw player.grenphase = false; player.attackframe = 0; player.attacktarget = 0; player.killtarget = 0; } else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS) { // put pin back player.grenphase = false; playSound(gSourceID[pinreplacesound], soundsrc.x, soundsrc.y, soundsrc.z); } } else { if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { // pull pin player.grenphase = true; playSound(gSourceID[pinpullsound], soundsrc.x, soundsrc.y, soundsrc.z); } } } } void look(Game* game, double xpos, double ypos) { if (game->menu) return; int width, height; const auto window = glfwGetCurrentContext(); glfwGetWindowSize(window, &width, &height); int xcenter = width / 2, ycenter = height / 2; glfwSetCursorPos(window, xcenter, ycenter); // we shouldn't need this auto& player = game->person[0]; auto factor = game->mouse_sensitivity; if (player.aimamount >= 1) factor *= (game->zoom) ? 0.05 : 0.8; if (slomo == 2) factor *= 0.6; camera.rotation += (xpos - xcenter) * factor; camera.rotation2 += (ypos - ycenter) * factor; // Smoothen camera movements camera.rotation = camera.rotation * 0.7 + camera.oldrotation * 0.3; camera.oldrotation = camera.rotation; player.playerrotation = 180 - camera.rotation; camera.rotation2 = camera.rotation2 * 0.7 + camera.oldrotation2 * 0.3; camera.rotation2 = std::min(std::max(camera.rotation2, -89.0f), 89.0f); camera.oldrotation2 = camera.rotation2; if (game->zoom || visions || player.aimamount <= 0 || player.whichgun == nogun || player.whichgun == grenade || player.whichgun == knife) { camera.visrotation = camera.rotation; camera.visrotation2 = camera.rotation2; } else { camera.visrotation = std::min(camera.rotation + 7, std::max(camera.rotation - 7, camera.visrotation)); camera.visrotation2 = std::min(camera.rotation2 + 15, std::max(camera.rotation2 - 15, camera.visrotation2)); } } void setListener(Game* game, 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 aimPlayer(Game* game) { auto& joints = game->person[0].skeleton.joints; auto point = joints[lefthand].position - joints[righthand].position; float aimrot = 0.0f, aimrot2 = 0.0f; switch (game->person[0].whichgun) { case assaultrifle: aimrot = -2.5f; break; case sniperrifle: aimrot = 4.0f; break; case shotgun: aimrot = randInt(-1000, 1000) / 500.0f - 1; aimrot2 = randInt(-1000, 1000) / 500.0f + 2; break; case handgun1: case handgun2: aimrot = -0.9f; auto k = thirdperson ? 0.35 : 0.65; point = joints[righthand].position - joints[head].position * k - joints[neck].position * (1 - k); break; } return DoRotation(point, aimrot2, game->person[0].playerrotation + aimrot, 0); } XYZ aimBot(Game* game, int j) { auto& bot = game->person[j]; float inaccuracy = 0.0f; switch (bot.whichgun) { case handgun1: case handgun2: inaccuracy = 8.0f; break; case assaultrifle: case shotgun: inaccuracy = 6.0f; break; case sniperrifle: inaccuracy = 2.0f; break; } auto& target = game->person[bot.killtarget]; if (target.skeleton.free) inaccuracy *= 3; auto& joints = target.skeleton.joints; XYZ aim = joints[abdomen].position; if (target.skeleton.free) inaccuracy *= 3; else aim = DoRotation(aim, 0, target.playerrotation, 0) + target.playercoords; auto& lefthandpos = joints[lefthand].position; aim -= bot.playercoords + DoRotation(lefthandpos, 0, bot.playerrotation, 0); return DoRotation( DoRotation(DoRotation(aim, 0, -bot.playerrotation, 0), randFloat() * inaccuracy, randFloat() * inaccuracy, 0), 0, bot.playerrotation, 0); } void Game::Tick() { if (person[1].health <= 0 || person[0].health <= 0 || killedinnocent) losedelay -= multiplier / 6; else timeremaining -= multiplier; if (timeremaining <= 0) { score += ++mission * 50 + 100; highscore = std::max(score, highscore); 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]); setMenu(this, beatgame = true); gameinprogress = 0; } else { updateSong(this); initGame(this); } } if (losedelay <= 0) { score -= (person[murderer].health > 0) ? 200 : 100; flashamount = 1; flashr = flashg = flashb = 0; alSourcePlay(gSourceID[soulinsound]); updateSong(this); 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); //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 = {(float) i * block_spacing, 0.0f, (float) 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; Splat(this, k); } 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 = {(float) i * block_spacing, 0.0f, (float) 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 = {(float) i * block_spacing, 0.0f, (float) 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 = {(float) i * block_spacing, 0.0f, (float) 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; Splat(this, k); } if(whichtri!=-1)inblock=1; } } } } if (person[k].playercoords.y <= 0) { person[k].onground = 1; person[k].playercoords.y = 0; Splat(this, k); 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.0f, 0.0f, -5.0f}; // Spawn people int cyclenum = 0; int blockspawnx = 0, blockspawny = 0; do { auto block = person[0].playercoords / block_spacing; blockspawnx = block.x + 0.5f + randInt(-1, 1); blockspawny = block.z + 0.5f + randInt(-1, 1); 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) { if (type == zombie_type) person[numpeople].type = zombietype; else if (randUint(evilprobability)) person[numpeople].type = civiliantype; else person[numpeople].type = eviltype; if(person[numpeople].type!=civiliantype&&blockspawnx==person[1].whichblockx&&blockspawny==person[1].whichblocky){ while((citypeoplenum[blockspawnx][blockspawny]>=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 + randInt(-1, 1); blockspawny = (person[0].playercoords.z + block_spacing / 2) / block_spacing + randInt(-1, 1); cyclenum++; } } person[numpeople].playerrotation=0; person[numpeople].whichcostume = casualcostumes + randUint(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 = randUint(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 = 0.98f + 0.04f * randFloat(); 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 = 0.8f + 0.4f * randFloat(); person[numpeople].health=100; person[numpeople].maxhealth=100; person[numpeople].playerrotation2=0; person[numpeople].lastdistancevictim=200000; 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 + randInt(-1, 1); blockspawny = (person[0].playercoords.z + block_spacing / 2) / block_spacing + randInt(-1, 1); cyclenum++; } } person[cycle].playerrotation=0; person[cycle].whichcostume = casualcostumes + randUint(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 = randUint(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= 0.98f + 0.04f * randFloat(); 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 = 0.8f + 0.4f * randFloat(); person[cycle].health=100; person[cycle].maxhealth=100; person[cycle].playerrotation2=0; 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[abdomen].position; temp.y=-.5; move = {}; 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 = {}; sprites.MakeSprite(bloodspritedown, .6, 1, .2, .2,bleedloc, vel, 3*person[i].bleeding); } } if (!person[i].skeleton.free) { // Gun switch (person[i].type) { case playertype: switch (person[i].whichgun) { case shotgun: person[i].recoil -= multiplier * 4; break; case sniperrifle: person[i].recoil -= multiplier * 2; break; case handgun1: case handgun2: person[i].recoil -= multiplier * 5; break; case assaultrifle: person[i].recoil-=multiplier * 10; break; } if (!person[0].aiming || visions) this->zoom = false; break; case eviltype: switch (person[i].whichgun) { case shotgun: case sniperrifle: person[i].recoil -= multiplier * 1; break; case handgun1: case handgun2: person[i].recoil -= multiplier * 2; break; case assaultrifle: person[i].recoil-=multiplier * 10; break; } break; } if (person[i].recoil < 0) person[i].recoil = 0; //Zombie eat if(i > 0 && person[i].targetanimation == zombieeatanim && person[person[i].killtarget].eaten == i) { person[person[i].killtarget].skeleton.joints[head].locked=1; person[person[i].killtarget].skeleton.joints[rightshoulder].locked=1; for(int k=0;k<2;k++){ person[person[i].killtarget].skeleton.joints[head].position=DoRotation(person[i].skeleton.joints[righthand].position,0,person[i].playerrotation,0)+person[i].playercoords; person[person[i].killtarget].skeleton.joints[head].velocity = {}; person[person[i].killtarget].skeleton.joints[rightshoulder].position=DoRotation(person[i].skeleton.joints[lefthand].position,0,person[i].playerrotation,0)+person[i].playercoords; person[person[i].killtarget].skeleton.joints[rightshoulder].velocity = {}; 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[head].locked=0; person[person[i].killtarget].skeleton.joints[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[randUint(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 (auto& joint : person[i].skeleton.joints) { joint.position += joint.offset; joint.position = DoRotation(joint.position, 0, person[i].playerrotation, 0); joint.position += person[i].playercoords; joint.realoldposition = joint.position; joint.velocity = DoRotation(joint.velocity, 0, person[i].playerrotation, 0); joint.velocity += person[i].velocity; joint.velocity += person[i].facing * 4; } } } //Rag doll if(person[i].skeleton.free==1&&person[i].longdead>0){ 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 = { (float) person[i].whichblockx * block_spacing, 0.0f, (float) 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 = {}; for (auto& joint : person[i].skeleton.joints) person[i].averageloc += joint.position; person[i].averageloc /= max_joints; person[i].playercoords=person[i].averageloc; if(person[i].longdead0)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 (auto& joint : person[i].skeleton.joints) if (joint.position.y > person[i].playercoords.y) person[i].playercoords.y = joint.position.y; //Find orientation XYZ firsttop=person[i].skeleton.joints[neck].position-person[i].skeleton.joints[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 = {}; if(person[i].targetanimation==getupfrontanim)person[i].playerrotation+=180; for (int j = 0; j < max_joints; ++j) { person[i].tempanimation.position[j][0]=person[i].skeleton.joints[j].position-person[i].playercoords; person[i].tempanimation.position[j][0]=DoRotation(person[i].tempanimation.position[j][0],0,-person[i].playerrotation,0); } } } XYZ velocity; if(person[0].attackframe>1||(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; if (person[person[0].killtarget].type != zombietype) { if (person[0].whichgun != knife) { playSound(gSourceID[headwhacksound], soundpos.x, soundpos.y, soundpos.z); } else { playSound(gSourceID[knifeslashsound], soundpos.x, soundpos.y, soundpos.z); person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[neck]; person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[neck]; person[person[0].killtarget].bleeding=1; person[person[0].killtarget].bleeddelay=1; person[0].bjoint1=&person[0].skeleton.joints[righthand]; person[0].bjoint2=&person[0].skeleton.joints[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[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[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[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 (auto& joint : person[person[0].killtarget].skeleton.joints) { joint.position = DoRotation(joint.position, 0, person[person[0].killtarget].playerrotation, 0); joint.position += person[person[0].killtarget].playercoords; joint.realoldposition = joint.position; joint.velocity = person[person[0].killtarget].velocity; joint.velocity.x += randInt(-4, 4); joint.velocity.y += randInt(-4, 4); joint.velocity.z += randInt(-4, 4); } if(person[0].whichgun!=knife){ person[person[0].killtarget].skeleton.joints[head].velocity+=DoRotation(flatfacing,0,40,0)*50; person[person[0].killtarget].skeleton.joints[head].velocity+=person[0].velocity*2; } } else if (!whacked) { whacked = true; if (person[0].whichgun != knife) { playSound(gSourceID[headwhacksound], soundpos.x, soundpos.y, soundpos.z); } else { playSound(gSourceID[knifeslashsound], soundpos.x, soundpos.y, soundpos.z); person[person[0].killtarget].bjoint1=&person[person[0].killtarget].skeleton.joints[neck]; person[person[0].killtarget].bjoint2=&person[person[0].killtarget].skeleton.joints[neck]; person[person[0].killtarget].bleeddelay=1; person[0].bjoint1=&person[0].skeleton.joints[righthand]; person[0].bjoint2=&person[0].skeleton.joints[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[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[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[neck].position,0,person[person[0].killtarget].playerrotation,0)+person[person[0].killtarget].playercoords, velocity*.1, 4); } person[person[0].killtarget].health-=200; person[person[0].killtarget].maxhealth-=20; person[person[0].killtarget].skeleton.free=1; person[person[0].killtarget].longdead=1; for (auto& joint : person[person[0].killtarget].skeleton.joints) { joint.position = DoRotation(joint.position, 0, person[person[0].killtarget].playerrotation, 0); joint.position += person[person[0].killtarget].playercoords; joint.realoldposition = joint.position; joint.velocity = person[person[0].killtarget].velocity; joint.velocity.x += randInt(-4, 4); joint.velocity.y += randInt(-4, 4); joint.velocity.z += randInt(-4, 4); } if(person[0].whichgun!=knife){ person[person[0].killtarget].skeleton.joints[head].velocity+=DoRotation(flatfacing,0,40,0)*50; person[person[0].killtarget].skeleton.joints[head].velocity+=person[0].velocity*2; } } } } //Tackle if (person[0].currentanimation == diveanim && visions == 0) { for (int i = 1; i < numpeople; i++) { if (person[i].skeleton.free > 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 += randInt(-4, 4); joint.velocity.y += randInt(-4, 4); joint.velocity.z += randInt(-4, 4); } } } // Empty magazine if (person[0].firing && person[0].ammo <= 0) { auto soundpos = person[0].playercoords - camera.position; playSound(gSourceID[clicksound], soundpos.x, soundpos.y, soundpos.z); person[0].firing = false; } 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) person[j].firing = false; else if (j) person[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 (!person[j].firing || person[j].aiming < 1 || person[j].recoil > 0) continue; if (j != 0 || person[j].whichgun != assaultrifle) person[j].firing = false; 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(this, j); else if (!zoom) aim = aimPlayer(this); else aim = facing; Normalise(&aim); int aimjoint; switch (person[j].whichgun) { case handgun1: case handgun2: aimjoint = rightwrist; break; default: aimjoint = lefthand; } start = person[j].playercoords + DoRotation(person[j].skeleton.joints[aimjoint].position, 0, person[j].playerrotation, 0); if (j == 0 && person[j].grenphase) { person[j].grenphase = false; sprites.MakeSprite(grenadesprite, 1, 1, 1, 1, start, aim * 200, 1.01); } 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 = randInt(-100, 100) / (crouch ? 60.0f : 50.0f); rot2 = crouch ? 1.5f : 2.3f; break; } camera.rotation -= rot; camera.rotation2 -= rot2; 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]; } auto soundpos = start - camera.position; playSound(gunsound, soundpos.x, soundpos.y, soundpos.z); } XYZ end {start + aim * 1000}; int bulletstrength=1; int firstpass=-1; 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 = {camera.position.x, 0.0f, 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.0f, 1.0f, 0.0f}; hitmove = {}; hitrotation=0; } if(m==0){ if(j==0&&slomo==2){ 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++; } bool penetrate = (numshots > 1) ? 0 : !randUint(3); 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 (auto& joint : person[whichhit].skeleton.joints) { joint.position = DoRotation(joint.position, 0, person[whichhit].playerrotation, 0); joint.position += person[whichhit].playercoords; joint.realoldposition = joint.position; joint.velocity = person[whichhit].velocity; joint.velocity.x += randInt(-4, 4); joint.velocity.y += randInt(-4, 4); joint.velocity.z += randInt(-4, 4); } } for (auto& joint : person[whichhit].skeleton.joints) { auto distance = findDistancefast(joint.position, hitstruct.hitlocation); if (distance < 200) { totalarea += 200 / distance; joint.velocity += aim * 200 / distance / totalarea * 200; } } } if(person[whichhit].health>0){ 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 (auto& joint : person[whichhit].skeleton.joints) { auto distance = findDistancefast(DoRotation(joint.position, 0, person[whichhit].playerrotation, 0) + person[whichhit].playercoords, hitstruct.hitlocation); if(distance < 200) { totalarea += 200 / distance; joint.offset += DoRotation(aim * 200 / distance / totalarea * 10, 0, -person[whichhit].playerrotation, 0); } if (findLengthfast(joint.offset) > 36) { Normalise(&joint.offset); joint.offset *= 6; } } } if(hitstruct.joint1->modelnum==headmodel&&person[whichhit].health<=0){ for (int j = 0; j < max_joints; ++j) { if(&person[whichhit].skeleton.joints[j]==hitstruct.joint1||&person[whichhit].skeleton.joints[j]==hitstruct.joint2){ if (j != abdomen && j != groin && j != neck) { sprites.MakeSprite(bloodspritedown, 0.8f, 1, 0.2f, 0.2f, person[whichhit].skeleton.joints[j].position, person[whichhit].skeleton.joints[j].velocity / 3, 9); for (int tmp = 0; tmp < 4; ++tmp) sprites.MakeSprite(bloodspritedown, 0.8f, 1, 0.2f, 0.2f, person[whichhit].skeleton.joints[j].position, DoRotation(person[whichhit].skeleton.joints[j].velocity / 3, randUint(360), randUint(360), 0) / 5, 5); person[whichhit].skeleton.DeleteJoint(j); person[whichhit].skeleton.broken=1; person[whichhit].health=-10000; person[whichhit].skeleton.joints[j].existing=0; if(person[whichhit].type==zombietype)score+=300; } } } } XYZ velocity; velocity=aim*-8; //blood if (hitstruct.joint1->modelnum != 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; playSound(hitsound, hitpos.x, hitpos.y, hitpos.z); } // 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 soundpos = finalwallhit - camera.position; playSound(gSourceID[wallhitsound], soundpos.x, soundpos.y, soundpos.z); } 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 XYZ* a = &lastshot[0]; *a += aim; XYZ* b = &lastshot[1]; XYZ* c = &camera.position; XYZ nearest {}; long 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); long 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; playSound(gSourceID[nearbulletsound], nearsound.x, nearsound.y, nearsound.z); } } } } 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[lefthand].position-person[j].skeleton.joints[righthand].position,0,person[j].playerrotation-2.5,0); if(person[j].whichgun==sniperrifle)aim=DoRotation(person[j].skeleton.joints[lefthand].position-person[j].skeleton.joints[righthand].position,0,person[j].playerrotation+4,0); if(person[j].whichgun==shotgun)aim=DoRotation(person[j].skeleton.joints[lefthand].position-person[j].skeleton.joints[righthand].position,0,person[j].playerrotation+4,0); if(person[j].whichgun==handgun1&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[righthand].position-(person[j].skeleton.joints[head].position*.65+person[j].skeleton.joints[neck].position*.35),0,person[j].playerrotation-.9,0); if(person[j].whichgun==handgun1&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[righthand].position-(person[j].skeleton.joints[head].position*.35+person[j].skeleton.joints[neck].position*.65),0,person[j].playerrotation-.9,0); if(person[j].whichgun==handgun2&&!thirdperson&&j==0)aim=DoRotation(person[j].skeleton.joints[righthand].position-(person[j].skeleton.joints[head].position*.65+person[j].skeleton.joints[neck].position*.35),0,person[j].playerrotation-.9,0); if(person[j].whichgun==handgun2&&(thirdperson||j!=0))aim=DoRotation(person[j].skeleton.joints[righthand].position-(person[j].skeleton.joints[head].position*.35+person[j].skeleton.joints[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[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[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[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[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[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 = {}; 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 = {(float) wherex * block_spacing, 0.0f, (float) 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 + randUint(2); alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc); alSourcePlay(gSourceID[whichsound]); } if (findLengthfast(sprites.velocity[i]) <= 10) sprites.velocity[i] = {}; } if(sprites.location[i].y<0){ impact=1; sprites.velocity[i].y *= -1.0f; sprites.velocity[i] *= 0.3f; sprites.location[i].y = 0.0f; if(sprites.type[i]==grenadesprite){ if(sprites.size[i]>1){ move = {}; sprites.location[i].y=-.5; XYZ normish = {0.0f, 1.0f, 0.0f}; 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 + randUint(2); alSourcefv(gSourceID[whichsound], AL_POSITION, gLoc); if (sprites.size[i] <= 1) alSourcePlay(gSourceID[whichsound]); } if (findLengthfast(sprites.velocity[i]) <= 10) sprites.velocity[i] = {}; } 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 (auto& joint : person[j].skeleton.joints) { joint.realoldposition = joint.position = DoRotation(joint.position, 0, person[j].playerrotation, 0) + person[j].playercoords; joint.velocity = person[j].velocity; joint.velocity.x += randInt(-4, 4); joint.velocity.y += randInt(-4, 4); joint.velocity.z += randInt(-4, 4); } 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 (auto& joint : person[j].skeleton.joints) { auto distance = findDistancefast(DoRotation(joint.position, 0, person[j].playerrotation, 0) + person[j].playercoords, hitstruct.hitlocation); if (distance < 200) { totalarea += 200 / distance; joint.offset += DoRotation(sprites.velocity[i] * 0.1 * 200 / distance / totalarea * 10, 0, -person[j].playerrotation, 0); } if (findLengthfast(joint.offset) > 9) { Normalise(&joint.offset); joint.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; wherex=(sprites.location[i].x+block_spacing/2)/block_spacing; wherey=(sprites.location[i].z+block_spacing/2)/block_spacing; move = {(float) wherex * block_spacing, 0.0f, (float) wherey * block_spacing}; XYZ temp; whichtri=sidewalkcollide.LineCheck2(overpoint,underpoint,&temp,move,cityrotation[wherex][wherey]*90); XYZ normish = {0.0f, 1.0f, 0.0f}; 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 = {}; 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[head]; person[k].bjoint2 = &person[k].skeleton.joints[neck]; for (auto& joint : person[k].skeleton.joints) { joint.position = DoRotation(joint.position, 0, person[k].playerrotation, 0); joint.position += person[k].playercoords; joint.realoldposition = joint.position; joint.velocity = DoRotation(joint.velocity, 0, person[k].playerrotation, 0); joint.velocity += person[k].velocity; joint.velocity.x += randInt(-9, 9); joint.velocity.y += randInt(-9, 9); joint.velocity.z += randInt(-9, 9); }} person[k].longdead=1; for (auto& joint : person[k].skeleton.joints) { relation = joint.position - sprites.location[i]; Normalise(&relation); auto distance = findDistance(joint.position, sprites.location[i]); if (distance > 1) joint.velocity += relation / distance * 300; else joint.velocity += relation * 300; // Sever stuff if (findLengthfast(joint.velocity) > 1500 && joint.existing && randUint(5)) { sprites.MakeSprite(bloodspritedown, 0.8, 1, 0.2, 0.2, joint.position, joint.velocity / 3, 9); person[k].skeleton.DeleteJoint(&joint - person[k].skeleton.joints); person[k].skeleton.broken=2; person[k].health=-10000; joint.existing = false; } } } } } } } } } //camera shake camerashake-=multiplier; if(camerashake<0)camerashake=0; //camera position XYZ average; if(!zoom)average=person[0].skeleton.joints[head].position*(person[0].aimamount/2+.5)+person[0].skeleton.joints[neck].position*((1-person[0].aimamount)/2); if(zoom)average=person[0].skeleton.joints[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){ 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; setListener(this, facing); if (score < 0) score = 0; }