// 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 .
#include
#include "Game.h"
#include "misc.h"
extern float multiplier;
extern int thirdperson;
extern bool visions;
extern float soundscalefactor;
extern unsigned int gSourceID[37];
extern Camera camera;
extern float rad2deg;
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) {
alSourceStop(gSourceID[rainsound]);
alSourceStop(gSourceID[visionsound]);
if (game->musictoggle) {
alSourceStop(gSourceID[game->whichsong]);
game->whichsong = mainmenusong;
alSourcef(gSourceID[game->whichsong], AL_PITCH, 1);
alSourcePlay(gSourceID[game->whichsong]);
}
alSourcePlay(gSourceID[souloutsound]);
setMenu(game, true);
game->flashamount = 1.0f;
game->flashr = game->flashg = game->flashb = 1.0f;
} 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
|| sqrlen(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]);
if (game->musictoggle)
alSourcef(gSourceID[game->whichsong],
AL_PITCH, 0.5f);
slomo = 2;
game->score -= 20;
}
} else if (key == keymap.psychic) {
if (visions ^= 1) {
game->flashamount = game->flashr = 1;
game->flashg = game->flashb = 0;
alSourceStop(gSourceID[visionsound]);
alSourcePlay(gSourceID[souloutsound]);
if (game->musictoggle)
alSourcef(gSourceID[game->whichsong],
AL_PITCH, 0.5f);
alSourcePlay(gSourceID[visionsound]);
player.oldplayercoords = player.playercoords;
} else {
game->flashamount = 1;
game->flashr = game->flashg = game->flashb = 1;
alSourceStop(gSourceID[visionsound]);
alSourcePlay(gSourceID[soulinsound]);
if (game->musictoggle)
alSourcef(gSourceID[game->whichsong],
AL_PITCH, 1.0f);
XYZ towards = player.playercoords - player.oldplayercoords;
if (towards.x || towards.z) {
towards = normalize(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 = player.oldplayercoords;
player.velocity = {};
}
} else if (key == keymap.switch_view) {
thirdperson = (thirdperson == 2) ? 0 : (thirdperson + 1);
}
if (!game->debug)
return;
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]);
if (game->musictoggle)
alSourcef(gSourceID[game->whichsong], AL_PITCH,
(slomo ^= 1) ? 0.5f : 1.0f);
} else if (key == keymap.force) {
auto facing = rotate({0, 0, -1}, -camera.rotation2, 0, 0);
facing = rotate(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
|| sqrlen(person.playercoords - player.playercoords) > 1000)
continue;
person.skeleton.free = 1;
person.longdead = 1;
for (auto& joint : person.skeleton.joints) {
joint.position = rotate(joint.position,
0, person.playerrotation, 0);
joint.position += person.playercoords;
joint.realoldposition = joint.position;
joint.velocity = rotate(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 && !game->menu)
multiplier /= 3;
if (slomo)
multiplier /= 5;
if (game->paused)
multiplier = 0;
}