summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Game.h10
-rw-r--r--src/GameInitDispose.cpp4
-rw-r--r--src/GameLoop.cpp60
-rw-r--r--src/GameTick.cpp458
-rw-r--r--src/Person.cpp9
-rw-r--r--src/Person.h3
-rw-r--r--src/Support.cpp14
-rw-r--r--src/Support.h8
-rw-r--r--src/main.zig8
9 files changed, 266 insertions, 308 deletions
diff --git a/src/Game.h b/src/Game.h
index 3c0776a..81bba21 100644
--- a/src/Game.h
+++ b/src/Game.h
@@ -54,8 +54,6 @@
 #define max_people_block 20
 
 class Game {
-	void saveHighScore();
-	void updateSong();
 	void handleMenu();
 	void handleToggles();
 	void mouseLook();
@@ -78,7 +76,6 @@ public:
 	int onblockx, onblocky;
 	bool cubetest;
 	bool disttest;
-	bool oldbutton;
 
 	bool initialized;
 
@@ -138,7 +135,6 @@ public:
 	int type;
 
 	int mouseoverbutton;
-	int oldmouseoverbutton;
 
 	Person person[max_people];
 
@@ -166,9 +162,12 @@ public:
 	GLvoid ReSizeGLScene(float fov, float near);
 	void DrawGLScene();
 
+	void updateSong();
+
 	// Game functions
 	void Tick();
 	void Splat(int k);
+	void saveHighScore();
 };
 #else // __cplusplus
 #include <stdbool.h>
@@ -183,8 +182,9 @@ extern "C" {
 	void initGl(Game* game);
 	void initGame(Game* game);
 	void resizeWindow(Game* game, int width, int height);
-	void handleKey(Game* game, int key, int action, int mods);
 	void look(Game* game, double xpos, double ypos);
+	void click(Game* game, int button, int action, int mods);
+	void handleKey(Game* game, int key, int action, int mods);
 	void setMenu(Game* game, bool value);
 	void eventLoop(Game* game);
 	void closeGame(Game* game);
diff --git a/src/GameInitDispose.cpp b/src/GameInitDispose.cpp
index 935945c..027d74b 100644
--- a/src/GameInitDispose.cpp
+++ b/src/GameInitDispose.cpp
@@ -80,8 +80,8 @@ Game* makeGame(Config config)
 	backwardskey = GLFW_KEY_S;
 	leftkey = GLFW_KEY_A;
 	rightkey = GLFW_KEY_D;
-	aimkey = GLFW_KEY_Q;
-	psychicaimkey = GLFW_KEY_E;
+	aimkey = GLFW_KEY_E;
+	psychicaimkey = GLFW_KEY_Q;
 	psychickey = GLFW_KEY_Z;
 
 	game->customlevels = config.custom_levels;
diff --git a/src/GameLoop.cpp b/src/GameLoop.cpp
index a927f2f..77ec774 100644
--- a/src/GameLoop.cpp
+++ b/src/GameLoop.cpp
@@ -24,6 +24,7 @@
 extern float multiplier;
 extern int thirdperson;
 extern int visions;
+extern float soundscalefactor;
 extern unsigned int gSourceID[100];
 extern unsigned int gSampleSet[100];
 extern Camera camera;
@@ -76,23 +77,56 @@ void handleKey(Game* game, int key, int action, int mods)
 			player.aimamount = 0;
 		}
 	} else if (key == GLFW_KEY_R) {
-		if (player.reloads[player.whichgun] > 0
+		if (player.whichgun != grenade
+		    && player.reloads[player.whichgun] > 0
 		    && player.reloading <= 0)
 			player.ammo = -1;
 	} else if (key == aimkey) {
 		player.aiming ^= 1;
 	} else if (key == psychicaimkey) {
-		game->flashamount = 0.5;
-		game->flashr = 1;
-		game->flashg = game->flashb = 0;
-		alSourcePlay(gSourceID[souloutsound]);
+		// 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 soundsrc = (player.playercoords
+					- camera.position) / soundscalefactor;
+				float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
+				alSourcefv(gSourceID[clicksound], AL_POSITION, gLoc);
+				alSourcePlay(gSourceID[clicksound]);
+
+				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;
+			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);
+			alSourcef(gSourceID[knifesong], AL_PITCH, 0.5f);
+			alSourcef(gSourceID[shootsong], AL_PITCH, 0.5f);
+			alSourcef(gSourceID[zombiesong], AL_PITCH, 0.5f);
+		}
 	} else if (key == psychickey) {
 		if (visions ^= 1) {
 			game->flashamount = game->flashr = 1;
@@ -186,14 +220,14 @@ void handleKey(Game* game, int key, int action, int mods)
 		}
 		break;
 	case GLFW_KEY_X:
-		if (!shift || player.grenphase)
+		if (player.grenphase)
 			break;
+		player.grenphase = 0;
 		player.ammo = -1;
 		player.whichgun++;
-		player.grenphase = 0;
-		player.reloads[player.whichgun] = 3;
 		if (player.whichgun > 7)
 			player.whichgun = 0;
+		player.reloads[player.whichgun] = 3;
 		break;
 	}
 }
diff --git a/src/GameTick.cpp b/src/GameTick.cpp
index c8b1111..8bea7cf 100644
--- a/src/GameTick.cpp
+++ b/src/GameTick.cpp
@@ -122,54 +122,196 @@ void Game::updateSong()
 	alSourcePlay(gSourceID[whichsong]);
 }
 
-void Game::handleMenu()
+void click(Game* game, int button, int action, int mods)
 {
-	Point mouseloc;
-	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;
+	if (game->menu) {
+		if (button != GLFW_MOUSE_BUTTON_LEFT || action != GLFW_PRESS)
+			return;
+		double xpos, ypos;
+		auto window = glfwGetCurrentContext();
+		glfwGetCursorPos(window, &xpos, &ypos);
+		double mousex = xpos * 640 / game->screenwidth;
+		double mousey = 480 - ypos * 480 / game->screenheight;
+
+		game->mouseoverbutton = 0;
+		if (mousex > 120 && mousex < 560) {
+			if (mousey > 235 && mousey < 305)
+				game->mouseoverbutton = 1;
+			else if (mousey > 112 && mousey < 182)
+				game->mouseoverbutton = 2;
+		}
+
+		switch (game->mouseoverbutton) {
+		case 1:
+			game->updateSong();
+			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]);
+			game->saveHighScore();
+			break;
+		}
+		return;
 	}
-	oldbutton = button;
 
-	switch (mouseoverbutton) {
-	case 1:
-		updateSong();
-		flashamount = flashr = flashg = flashb = 1;
-		alSourcePlay(gSourceID[soulinsound]);
+	auto& player = game->person[0];
+	auto& weapon = player.whichgun;
 
-		if (!gameinprogress) {
-			mission = 0;
-			initGame(this);
+	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 || weapon == grenade
+	        || 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 (visions)
-			alSourcePlay(gSourceID[visionsound]);
+		if (attacking) {
+			player.attacktarget = 0;
+			player.attackframe = 0;
+			game->whacked = false;
+			return;
+		}
+	}
 
-		gameinprogress = 1;
-		setMenu(this, false);
-		break;
-	case 2:
-		if (gameinprogress) {
-			flashamount = flashr = flashg = flashb = 1;
-			gameinprogress = 0;
-		} else {
-			flashamount = flashr = 1;
-			flashg = flashb = 0;
-			glfwSetWindowShouldClose(glfwGetCurrentContext(), true);
+	// 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;
+			}
 		}
 
-		alSourcePlay(gSourceID[losesound]);
-		saveHighScore();
-		break;
+		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[skeleton.jointlabels[righthand]];
+		auto soundsrc = (DoRotation(hand.position, 0, player.playerrotation, 0)
+			+ player.playercoords - camera.position) / soundscalefactor;
+		float gLoc[] {soundsrc.x, soundsrc.y, soundsrc.z};
+		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;
+				alSourcefv(gSourceID[pinreplacesound], AL_POSITION, gLoc);
+				alSourcePlay(gSourceID[pinreplacesound]);
+			}
+		} else {
+			if (button == GLFW_MOUSE_BUTTON_LEFT
+			    && action == GLFW_PRESS) { // pull pin
+				player.grenphase = true;
+				alSourcefv(gSourceID[pinpullsound], AL_POSITION, gLoc);
+				alSourcePlay(gSourceID[pinpullsound]);
+			}
+		}
 	}
 }
 
@@ -305,11 +447,6 @@ XYZ Game::aimBot(int j)
 
 void Game::Tick()
 {
-	if (this->menu) {
-		handleMenu();
-		return;
-	}
-
 	if (person[1].health <= 0 || person[0].health <= 0 || killedinnocent)
 		losedelay -= multiplier / 6;
 	else
@@ -963,10 +1100,6 @@ void Game::Tick()
 					person[i].recoil-=multiplier * 10;
 					break;
 				}
-				this->zoom = person[0].whichgun == sniperrifle
-					&& person[0].aiming >=1 && !visions
-					&& person[0].currentanimation == crouchanim
-					&& person[0].targetanimation == crouchanim;
 				break;
 			case eviltype:
 				switch (person[i].whichgun) {
@@ -1519,184 +1652,6 @@ void Game::Tick()
 		}
 	}
 
-	// Grenade
-	if (Button() && person[0].whichgun == grenade && person[0].ammo > 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;i<numpeople;i++){
-
-				if(person[i].skeleton.free<1&&(person[i].whichgun!=nogun)&&findDistancefast(person[i].playercoords,person[0].playercoords+flatfacing)<12){
-
-					attacking=1;
-
-					if(person[0].killtarget==-1||findDistancefast(person[i].playercoords,person[0].playercoords)<closedistance){
-
-						person[0].killtarget=i;
-
-						closedistance=findDistancefast(person[i].playercoords,person[0].playercoords);
-
-					}
-
-				}
-
-			}
-
-			if(attacking){
-
-				score+=150;
-
-				person[0].aiming=1;
-
-				person[0].whichgun=person[person[0].killtarget].whichgun;
-
-				person[0].ammo=person[person[0].killtarget].ammo;
-
-				person[person[0].killtarget].whichgun=nogun;
-
-				person[person[0].killtarget].killtarget=-1;
-
-				person[0].targetframe=0;
-
-				person[0].targetanimation=throwanim;
-
-				person[0].target=1;
-
-				person[0].speed=1;
-
-				person[person[0].killtarget].targetframe=0;
-
-				person[person[0].killtarget].targetanimation=thrownanim;
-
-				person[person[0].killtarget].target=1;
-
-				person[person[0].killtarget].playercoords=person[0].playercoords;
-
-				person[person[0].killtarget].playerrotation=person[0].playerrotation;
-
-				person[person[0].killtarget].speed=person[0].speed;
-
-				person[person[0].killtarget].speedmult=1;
-
-			}
-
-		}
-
-	}
-
-	//Gun whacking
-
-	if(Button()&&(person[0].aiming==0||person[0].ammo<=0||person[0].whichgun==nogun||person[0].whichgun==knife||person[0].targetanimation==joganim)&&person[0].currentanimation!=crouchanim&&person[0].targetanimation!=throwanim&&person[0].whichgun!=grenade&&person[0].targetanimation!=crouchanim&&visions==0){
-
-		if(person[0].attackframe==-1||person[person[0].killtarget].skeleton.free==1){
-
-			bool attacking=0;
-
-			person[0].killtarget=-1;
-
-			float closedistance=-1;
-
-			for(int i=1;i<numpeople;i++){
-
-				if(person[i].existing&&person[i].type!=viptype&&person[i].skeleton.free<1&&findDistancefast(person[i].playercoords,person[0].playercoords+flatfacing)<12+(person[0].whichgun==knife)*10){
-
-					if(person[0].killtarget==-1||findDistancefast(person[i].playercoords,person[0].playercoords)<closedistance){
-
-						attacking=1;
-
-						person[0].killtarget=i;
-
-						closedistance=findDistancefast(person[i].playercoords,person[0].playercoords);
-
-					}
-
-				}
-
-			}
-
-			if(attacking){
-
-				person[0].attacktarget=0;
-
-				person[0].attackframe=0;
-
-			}
-
-			whacked=0;
-
-		}
-
-	}
-
 	XYZ velocity;
 
 	if(person[0].attackframe>1||(person[0].attackframe>=0&&person[0].currentanimation==joganim)){
@@ -1841,32 +1796,16 @@ void Game::Tick()
 		}
 	}
 
-	// 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;
+	// Empty magazine
+	if (person[0].firing && person[0].ammo <= 0) {
 		float gLoc[] {
-			coords.x / soundscalefactor,
-			coords.y / soundscalefactor,
-			coords.z / soundscalefactor,
+			person[0].playercoords.x / soundscalefactor,
+			person[0].playercoords.y / soundscalefactor,
+			person[0].playercoords.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;
+		person[0].firing = false;
 	}
 
 	XYZ wallhit;
@@ -1878,7 +1817,7 @@ void Game::Tick()
 	int hitpoly = 0;
 	float hitrotation = 0.0f;
 	Model* model = NULL;
- 
+
 	for (int j = 0; j < numpeople; j++) {
 		if (j && person[j].type != eviltype)
 			continue;
@@ -1887,9 +1826,9 @@ void Game::Tick()
 		    || person[j].reloading > 0
 		    || person[j].targetanimation == joganim
 		    || person[j].aimamount < 1)
-			firing = false;
+			person[j].firing = false;
 		else if (j)
-			firing = person[j].whichgun != nogun
+			person[j].firing = person[j].whichgun != nogun
 				&& person[j].whichgun != knife
 				&& person[j].killtargetvisible
 				&& person[j].shotdelay < 0;
@@ -1914,8 +1853,10 @@ void Game::Tick()
 			person[j].aiming = 0;
 		}
 
-		if (!firing || person[j].aiming < 1 || person[j].recoil > 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;
@@ -1953,6 +1894,12 @@ void Game::Tick()
 				+ 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);
@@ -2021,12 +1968,6 @@ void Game::Tick()
 			}
 
 			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;
@@ -2624,7 +2565,6 @@ void Game::Tick()
 			if(person[j].aiming>=1){
 
 				//Firing
-
 				XYZ end, aim;
 
 				HitStruct hitstruct,temphitstruct;
diff --git a/src/Person.cpp b/src/Person.cpp
index 9e49cbb..d529143 100644
--- a/src/Person.cpp
+++ b/src/Person.cpp
@@ -394,11 +394,10 @@ void Person::DoAnimations(int who)
 				if(aimamount>0)aimamount-=multiplier*4;
 				if(aimamount<0)aimamount=0;
 			}
-			if(grenphase==1){
+			if (grenphase) {
 				if(grenamount<1)grenamount+=multiplier*4;
 				if(grenamount>1)grenamount=1;
-			}
-			if(grenphase==0){
+			} else {
 				if(grenamount>0)grenamount-=multiplier*4;
 				if(grenamount<0)grenamount=0;
 			}
@@ -972,7 +971,7 @@ int Person::DrawSkeleton(int who)
 		glTranslatef(0, 0, 0.05);
 		if (reloading <= 0) {
 			gunmodels[grenadebasemodel].draw();
-			if (grenphase == 0)
+			if (!grenphase)
 				gunmodels[grenadepinmodel].draw();
 			glTranslatef(0, 0, 0.005);
 			gunmodels[grenadespoonmodel].draw();
@@ -983,7 +982,7 @@ int Person::DrawSkeleton(int who)
 		glTranslatef(left_wrist.x, left_wrist.y, left_wrist.z);
 		glRotatef(-90, 1, 0, 0);
 		glTranslatef(0, 0, -0.15);
-		if (reloading <= 0 && grenphase == 1)
+		if (reloading <= 0 && grenphase)
 			gunmodels[grenadepinmodel].draw();
 		glPopMatrix();
 		break;
diff --git a/src/Person.h b/src/Person.h
index aa3a53e..840876d 100644
--- a/src/Person.h
+++ b/src/Person.h
@@ -53,6 +53,7 @@ class Person
 		XYZ facing;
 		XYZ velocity;
 		float shotdelay;
+		bool firing;
 		bool litup;
 
 		bool existing;
@@ -77,7 +78,7 @@ class Person
 
 		float speed;
 		bool aiming;
-		int grenphase;
+		bool grenphase;
 		float grenamount;
 		float aimamount;
 		float speedmult;
diff --git a/src/Support.cpp b/src/Support.cpp
index fc2b0ac..f7e726a 100644
--- a/src/Support.cpp
+++ b/src/Support.cpp
@@ -21,20 +21,6 @@ int Random()
 #endif
 }
 
-void GetMouse(Point *p)
-{
-	double xpos, ypos;
-	glfwGetCursorPos(glfwGetCurrentContext(), &xpos, &ypos);
-	p->h = floor(xpos);
-	p->v = floor(ypos);
-}
-
-int Button(void)
-{
-	const auto window = glfwGetCurrentContext();
-	return glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
-}
-
 bool IsKeyDown(int key)
 {
 	const auto window = glfwGetCurrentContext();
diff --git a/src/Support.h b/src/Support.h
index 7d95073..b033272 100644
--- a/src/Support.h
+++ b/src/Support.h
@@ -22,18 +22,10 @@ typedef struct UnsignedWide
 	unsigned int hi;
 } UnsignedWide;
 
-typedef struct Point
-{
-	int h;
-	int v;
-} Point;
-
 #define SetFPos(fildes, whence, offset) lseek(fildes, offset, whence)
 #define FSClose(fildes) close(fildes)
 
 int Random();
-void GetMouse(Point *p);
-int Button(void);
 bool IsKeyDown(int key);
 
 void loadOgg(char* filename, ALuint buffer, ALuint source);
diff --git a/src/main.zig b/src/main.zig
index 17c4119..b964536 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -40,6 +40,11 @@ fn look(window: ?*gf.Window.Impl, xpos: f64, ypos: f64) callconv(.C) void {
     legacy.look(game, xpos, ypos);
 }
 
+fn click(window: ?*gf.Window.Impl, button: c_int,
+         action: c_int, mods: c_int) callconv(.C) void {
+    legacy.click(game, button, action, mods);
+}
+
 pub fn main() !void {
     const loca = try Loca.init(allocator, .{});
     defer loca.deinit();
@@ -58,10 +63,11 @@ pub fn main() !void {
 
     if (try gf.rawMouseMotionSupported())
         try window.setInputMode(.raw_mouse_motion, true);
+    try window.setCursorPosCallback(look);
     try window.setInputMode(.sticky_mouse_buttons, true);
+    try window.setMouseButtonCallback(click);
     try window.setInputMode(.sticky_keys, true);
     try window.setKeyCallback(handleKey);
-    try window.setCursorPosCallback(look);
 
     const device = try al.Device.init(null);
     defer device.deinit() catch unreachable;