aboutsummaryrefslogblamecommitdiff
path: root/src/GameLoop.cpp
blob: caa3c1ba2467873e5f653832571bffedff519e3b (plain) (tree)
1
2
3
4
5



                                          
                                         















                                                                         

                
                 
                 
 
                        
                       
                   
                              
                                  
                     
                     
               
                       
                 
                         
 
                                                         
 
                                 
                       


                                                    
                                    














                                                                      
                                               
                                      
                                        







                                                                     
                                          

                                                          

                                             
                                       
                                   
                                               











                                                                                 


                                                                                      

















                                                                  
 

                                          
 



                                                                         
                                           























                                                                             
                                                                                  











                                                                                
 

                         
                                        
                                                                         
                                        
                                        
                                         
                                                     








                                                                              
                                                                       
                                                      
 




                                                                            
                                         

                                                 
 



                                                                           
                                                                       


                                                                           
                                                              


                                                                   

                         
                                                 
                                     
                               
                                     

                                  

                                            
                                                    
         

 





                                                                                
                          
 
                                   




                                              
                                        




                                
 
// Event loop handler
// Copyright (C) 2002  David Rosen
// Copyright (C) 2003  Zachary Jack Slater
// Copyright (C) 2003  Steven Fuller
// 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 <https://www.gnu.org/licenses/>.

#include <cmath>

#include "Game.h"
#include "misc.h"

extern float multiplier;
extern int thirdperson;
extern int visions;
extern float soundscalefactor;
extern unsigned int gSourceID[37];
extern Camera camera;
extern float rad2deg;
extern Fog fog;
extern int environment;
extern int slomo;
extern struct Key keymap;

void handleKey(Game* game, int key, int action, int mods)
{
	if (action != GLFW_PRESS)
		return;
	auto& player = game->person[0];
	if (key == GLFW_KEY_ESCAPE) {
		alSourcePause(gSourceID[rainsound]);
		setMenu(game, true);
		alSourcePlay(gSourceID[souloutsound]);
		game->flashamount = 1.0f;
		game->flashr = game->flashg = game->flashb = 1.0f;
		alSourceStop(gSourceID[visionsound]);
		game->whichsong = mainmenusong;
		alSourceStop(gSourceID[knifesong]);
		alSourceStop(gSourceID[shootsong]);
		alSourceStop(gSourceID[zombiesong]);
		alSourceStop(gSourceID[mainmenusong]);
		alSourcef(gSourceID[knifesong], AL_MIN_GAIN, 0);
		alSourcef(gSourceID[shootsong], AL_MIN_GAIN, 0);
		alSourcef(gSourceID[zombiesong], AL_MIN_GAIN, 0);
		alSourcef(gSourceID[mainmenusong], AL_MIN_GAIN, 0);
		alSourcePlay(gSourceID[game->whichsong]);
		alSourcef(gSourceID[game->whichsong], AL_MIN_GAIN, 1);
	} else if (key == keymap.laser_sight) {
		game->lasersight ^= 1;
	} else if (key == keymap.dive) {
		if (player.playerrotation == player.playerlowrotation
		    && player.targetanimation == joganim
		    && player.currentanimation == joganim
		    && !player.backwardsanim && !visions) {
			player.targetanimation = diveanim;
			player.targetframe = player.target = 0;
			player.aimamount = 0;
		}
	} else if (key == keymap.reload) {
		if (player.whichgun != grenade
		    && player.reloads[player.whichgun] > 0
		    && player.reloading <= 0)
			player.ammo = -1;
	} else if (key == keymap.aim) {
		player.aiming ^= 1;
	} else if (key == keymap.psychic_aim) {
		// Picking up gun from rag doll
		if (player.currentanimation == crouchanim
		    && (!player.aiming || player.whichgun == nogun
		        || player.whichgun == knife
		        || player.whichgun == grenade)) {
			for (int i = 1; i < game->numpeople; ++i) {
				auto& person = game->person[i];
				if (!person.skeleton.free
				    || findDistancefast(player.playercoords,
				                        person.averageloc) > 200)
					continue;

				auto soundpos = player.playercoords - camera.position;
				playSound(gSourceID[clicksound],
					soundpos.x, soundpos.y, soundpos.z);

				auto tmp_gun = player.whichgun;
				player.whichgun = person.whichgun;
				person.whichgun = tmp_gun;

				auto tmp_ammo = player.ammo;
				player.ammo = person.ammo;
				person.ammo = tmp_ammo;

				player.aiming = 1;
				player.aimamount = 0;
				break;
			}
		} else {
			game->flashamount = 0.5;
			game->flashr = 1;
			game->flashg = game->flashb = 0;
			alSourcePlay(gSourceID[souloutsound]);

			slomo = 2;
			game->score -= 20;

			alSourcef(gSourceID[knifesong], AL_PITCH, 0.5f);
			alSourcef(gSourceID[shootsong], AL_PITCH, 0.5f);
			alSourcef(gSourceID[zombiesong], AL_PITCH, 0.5f);
		}
	} else if (key == keymap.psychic) {
		if (visions ^= 1) {
			game->flashamount = game->flashr = 1;
			game->flashg = game->flashb = 0;
			alSourceStop(gSourceID[visionsound]);
			alSourcePlay(gSourceID[souloutsound]);

			alSourcef(gSourceID[knifesong], AL_PITCH, 0.5f);
			alSourcef(gSourceID[shootsong], AL_PITCH, 0.5f);
			alSourcef(gSourceID[zombiesong], AL_PITCH, 0.5f);
			alSourcePlay(gSourceID[visionsound]);
			game->bodycoords = player.oldplayercoords;
		} else {
			game->flashamount = 1;
			game->flashr = game->flashg = game->flashb = 1;
			alSourceStop(gSourceID[visionsound]);
			alSourcePlay(gSourceID[soulinsound]);

			alSourcef(gSourceID[knifesong], AL_PITCH, 1.0f);
			alSourcef(gSourceID[shootsong], AL_PITCH, 1.0f);
			alSourcef(gSourceID[zombiesong], AL_PITCH, 1.0f);

			XYZ towards = player.playercoords - game->bodycoords;
			if (towards.x || towards.z) {
				Normalise(&towards);
				camera.rotation = asin(towards.x) * 180.0f / M_PI;
				if (towards.z > 0)
					camera.rotation = 180 - camera.rotation;

				camera.visrotation = camera.rotation;
				camera.oldrotation = camera.rotation;
			}

			player.playercoords = game->bodycoords;
			player.oldplayercoords = game->bodycoords;
			player.velocity = 0;
		}
	}

	if (!game->debug)
		return;
	if (key == keymap.switch_view) {
		thirdperson = (thirdperson == 2) ? 0 : (thirdperson + 1);
	} else if (key == keymap.skip) {
		game->timeremaining = 0;
	} else if (key == keymap.pause) {
		alSourcePlay(gSourceID[soulinsound]);
		game->paused = 1 - game->paused;
	} else if (key == keymap.slomo) {
		alSourcePlay(gSourceID[soulinsound]);
		auto pitch = (slomo ^= 1) ? 0.5f : 1.0f;
		alSourcef(gSourceID[knifesong], AL_PITCH, pitch);
		alSourcef(gSourceID[shootsong], AL_PITCH, pitch);
		alSourcef(gSourceID[zombiesong], AL_PITCH, pitch);
	} else if (key == keymap.force) {
		auto facing = DoRotation({0, 0, -1}, -camera.rotation2, 0, 0);
		facing = DoRotation(facing, 0, 0 - camera.rotation, 0);
		alSourcePlay(gSourceID[souloutsound]);

		for (int i = 1; i < game->numpeople; i++) {
			auto& person = game->person[i];
			if (person.skeleton.free == 1
			    || findDistancefast(person.playercoords,
						player.playercoords) > 1000)
				continue;
			person.skeleton.free = 1;
			person.longdead = 1;

			for (auto& joint : person.skeleton.joints) {
				joint.position = DoRotation(joint.position,
					0, person.playerrotation, 0);
				joint.position += person.playercoords;
				joint.realoldposition = joint.position;
				joint.velocity = DoRotation(joint.velocity,
					0, person.playerrotation, 0);
				joint.velocity += person.velocity;
				joint.velocity += facing * 50;
				joint.velocity.x += randInt(-9, 9);
				joint.velocity.y += randInt(-9, 9);
				joint.velocity.z += randInt(-9, 9);
			}
		}
	} else if (key == keymap.switch_weapon) {
		if (player.grenphase)
			return;
		player.grenphase = 0;
		player.ammo = -1;
		player.whichgun++;
		if (player.whichgun > 7)
			player.whichgun = 0;
		player.reloads[player.whichgun] = 3;
	}
}

void setMenu(Game* game, bool val)
{
	glfwSetInputMode(glfwGetCurrentContext(), GLFW_CURSOR,
		(game->menu = val) ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
}

void eventLoop(Game* game)
{
	auto start = glfwGetTime();
	game->Tick();
	game->DrawGLScene();

	do multiplier = glfwGetTime() - start;
	while (multiplier < 1.0f / 69);
	if (visions == 1 && !game->menu)
		multiplier /= 3;
	if (slomo)
		multiplier /= 5;
	if (game->paused)
		multiplier = 0;
}