From 7cd5eb4c77de9fda4946de7e1c2384d0c2a0253e Mon Sep 17 00:00:00 2001
From: MirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Date: Sun, 7 Apr 2013 15:41:33 -1000
Subject: [PATCH] Swing the camera down when the player lands on the ground,
 based on the velocity the surface is hit with.

---
 src/camera.cpp      | 29 +++++++++++++++++++++++++++--
 src/camera.h        |  2 ++
 src/localplayer.cpp |  3 +++
 src/localplayer.h   |  2 ++
 4 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/camera.cpp b/src/camera.cpp
index 735a8d1e9..211ecfd70 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -67,6 +67,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
 	m_view_bobbing_anim(0),
 	m_view_bobbing_state(0),
 	m_view_bobbing_speed(0),
+	m_view_bobbing_fall(0),
 
 	m_digging_anim(0),
 	m_digging_button(-1),
@@ -134,6 +135,13 @@ inline f32 my_modf(f32 x)
 
 void Camera::step(f32 dtime)
 {
+	if(m_view_bobbing_fall > 0)
+	{
+		m_view_bobbing_fall -= 3 * dtime;
+		if(m_view_bobbing_fall <= 0)
+			m_view_bobbing_fall = -1; // Mark the effect as finished
+	}
+
 	if (m_view_bobbing_state != 0)
 	{
 		//f32 offset = dtime * m_view_bobbing_speed * 0.035;
@@ -237,11 +245,28 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
 	m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
 	m_playernode->updateAbsolutePosition();
 
-	//Get camera tilt timer (hurt animation)
+	// Get camera tilt timer (hurt animation)
 	float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75);
 
+	// Fall bobbing animation
+	float fall_bobbing = 0;
+	if(player->camera_impact >= 1)
+	{
+		if(m_view_bobbing_fall == -1) // Effect took place and has finished
+			player->camera_impact = m_view_bobbing_fall = 0;
+		else if(m_view_bobbing_fall == 0) // Initialize effect
+			m_view_bobbing_fall = 1;
+
+		// Convert 0 -> 1 to 0 -> 1 -> 0
+		fall_bobbing = m_view_bobbing_fall < 0.5 ? m_view_bobbing_fall * 2 : -(m_view_bobbing_fall - 0.5) * 2 + 1;
+		// Smoothen and invert the above
+		fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1;
+		// Amplify according to the intensity of the impact
+		fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5;
+	}
+
 	// Set head node transformation
-	m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength,0));
+	m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0));
 	m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength));
 	m_headnode->updateAbsolutePosition();
 
diff --git a/src/camera.h b/src/camera.h
index 989dcb718..0ed5c20d2 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -166,6 +166,8 @@ class Camera
 	s32 m_view_bobbing_state;
 	// Speed of view bobbing animation
 	f32 m_view_bobbing_speed;
+	// Fall view bobbing
+	f32 m_view_bobbing_fall;
 
 	// Digging animation frame (0 <= m_digging_anim < 1)
 	f32 m_digging_anim;
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 9c70c8b2f..6b7b0943c 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -329,6 +329,9 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
 	if(!touching_ground_was && touching_ground){
 		MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround");
 		m_gamedef->event()->put(e);
+
+		// Set camera impact value to be used for view bobbing
+		camera_impact = getSpeed().Y * -1;
 	}
 
 	{
diff --git a/src/localplayer.h b/src/localplayer.h
index 9ac2bc682..8c3041c04 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -59,6 +59,8 @@ class LocalPlayer : public Player
 	float last_yaw;
 	unsigned int last_keyPressed;
 
+	float camera_impact;
+
 private:
 	// This is used for determining the sneaking range
 	v3s16 m_sneak_node;
-- 
GitLab