From: MirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>
Date: Sat, 27 Aug 2011 13:31:25 +0000 (+0300)
Subject: Port damage / velocity based player leaning from Xonotic, with good defaults for VT
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=d69c51860ce358a3ec72abaf2be51017bb81fb46;p=voretournament%2Fvoretournament.git

Port damage / velocity based player leaning from Xonotic, with good defaults for VT
---

diff --git a/data/defaultVT.cfg b/data/defaultVT.cfg
index 1a8269be..84e235fa 100644
--- a/data/defaultVT.cfg
+++ b/data/defaultVT.cfg
@@ -299,6 +299,13 @@ set g_respawn_ghosts 1 "if 1 dead bodies become ghosts and float away when the p
 set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate"
 set g_respawn_ghosts_maxtime 6 "maximum amount of time a respawn ghost can last, minimum time is half this value. 0 disables and ghosts fade when the body would"
 
+set g_leanplayer_damage 0.1 "lean players that are shot by this amount, based on the force they take"
+set g_leanplayer_damage_fade 0.001 "how fast players return to normal angles, based on damage taken"
+set g_leanplayer_damage_max 10 "damage leaning is limited to this amount"
+set g_leanplayer_acceleration 0.05 "lean players as they accelerate, by this amount"
+set g_leanplayer_acceleration_fade 5 "velocity averaging steps for acceleration, higher values cause a shorter leaning"
+set g_leanplayer_acceleration_max 10 "acceleration leaning is limited to this amount"
+
 set sv_gibhealth -150 "Amount of health a dead body must have in order to get gibbed, influenced by player size"
 
 // fragmessage: This allows extra information to be displayed with the frag centerprints. 
diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc
index 2da8bd65..08beea92 100644
--- a/data/qcsrc/server/cl_client.qc
+++ b/data/qcsrc/server/cl_client.qc
@@ -928,6 +928,7 @@ void PutClientInServer (void)
 
 		self.angles_z = 0; // never spawn tilted even if the spot says to
 		self.fixangle = TRUE; // turn this way immediately
+		self.leanangle_damage_force = '0 0 0';
 		self.velocity = '0 0 0';
 		self.avelocity = '0 0 0';
 		self.punchangle = '0 0 0';
@@ -2441,6 +2442,7 @@ Called every frame for each client before the physics are run
 */
 void() ctf_setstatus;
 .float items_added;
+.vector avg_vel;
 void PlayerPreThink (void)
 {
 	self.stat_game_starttime = game_starttime;
@@ -2545,6 +2547,64 @@ void PlayerPreThink (void)
 			self.fixangle = TRUE;
 		}
 
+		if(!self.stat_eaten)
+		{
+			// lean the player with damage and acceleration
+			// credits go to divVerent for these maths :)
+			vector L0, L1, LF, LA;
+
+			LA = AnglesTransform_FromAngles(self.angles);
+
+			// acceleration leaning
+			if(cvar("g_leanplayer_acceleration"))
+			{
+				// average velocity to obtain a smooth acceleration
+				float f;
+				f = frametime * cvar("g_leanplayer_acceleration_fade");
+				self.avg_vel = self.avg_vel * (1 - f) + self.velocity * f;
+			}
+
+			vector accel;
+			accel = self.velocity - self.avg_vel * cvar("g_leanplayer_acceleration"); // acceleration
+
+			// bound angles to the specified limit
+			accel_x = bound(-cvar("g_leanplayer_acceleration_max"), accel_x, cvar("g_leanplayer_acceleration_max"));
+			accel_y = bound(-cvar("g_leanplayer_acceleration_max"), accel_y, cvar("g_leanplayer_acceleration_max"));
+			accel_z = bound(-cvar("g_leanplayer_acceleration_max"), accel_z, cvar("g_leanplayer_acceleration_max"));
+
+			L0_x = vlen(accel);
+			L0_y = L1_y = vectoyaw(accel);
+
+			L0 = AnglesTransform_FromAngles(L0);
+			L1 = AnglesTransform_FromAngles(L1);
+			LF = AnglesTransform_Multiply(AnglesTransform_Invert(L1), L0);
+			LA = AnglesTransform_Multiply(LA, LF);
+			// end of acceleration leaning
+
+			// damage leaning
+			L0 = vectoangles(self.leanangle_damage_loc);
+			L1 = vectoangles(self.leanangle_damage_loc + self.leanangle_damage_force);
+
+			L0 = AnglesTransform_FromAngles(L0);
+			L1 = AnglesTransform_FromAngles(L1);
+			LF = AnglesTransform_Multiply(AnglesTransform_Invert(L1), L0);
+
+			LA = AnglesTransform_Multiply(LA, LF);
+
+			// fade the player back to normal rotation each frame, based on how much damage they have taken
+			// this is used to simulate damage, so a wounded player will get back up slower
+			if(self.leanangle_damage) // prevent division by zero
+			if(self.leanangle_damage_force) // extra safety
+			{
+				float leanangle_damage_fade;
+				leanangle_damage_fade = 1 / (1 + (self.leanangle_damage * cvar("g_leanplayer_damage_fade")));
+				self.leanangle_damage_force = self.leanangle_damage_force * leanangle_damage_fade;
+			}
+			// end of damage leaning
+
+			self.angles = AnglesTransform_Normalize(AnglesTransform_ToAngles(LA), TRUE);
+		}
+
 		SetPlayerSize();
 
 		if(frametime)
diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh
index 2857578f..9df71320 100644
--- a/data/qcsrc/server/defs.qh
+++ b/data/qcsrc/server/defs.qh
@@ -297,6 +297,8 @@ float timeoutStatus; // (values: 0, 1, 2) contains whether a timeout is not acti
 entity timeoutInitiator; // contains the entity of the player who started the last timeout
 float orig_slowmo; // contains the value of cvar("slowmo") so that, after timeout finished, it isn't set to slowmo 1 necessarily
 .vector lastV_angle; //used when pausing the game in order to force the player to keep his old view angle fixed
+.vector leanangle_damage_loc, leanangle_damage_force; // used for leaning the player model
+.float leanangle_damage;
 entity timeoutHandler; //responsible for centerprinting the timeout countdowns and playing sounds
 void timeoutHandler_Think();
 void evaluateTimeout();
diff --git a/data/qcsrc/server/g_damage.qc b/data/qcsrc/server/g_damage.qc
index 8bb67e1c..02411d41 100644
--- a/data/qcsrc/server/g_damage.qc
+++ b/data/qcsrc/server/g_damage.qc
@@ -864,6 +864,19 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
 				}
 			}
 		}
+
+		// lean the player based on the amount of damage taken
+		if(cvar("g_leanplayer_damage"))
+		{
+			targ.leanangle_damage_loc = hitloc - targ.origin;
+			targ.leanangle_damage_force += force * cvar("g_leanplayer_damage"); // keep existing force if any
+			targ.leanangle_damage = damage;
+
+			// bound angles to the specified limit
+			targ.leanangle_damage_force_x = bound(-cvar("g_leanplayer_damage_max"), targ.leanangle_damage_force_x, cvar("g_leanplayer_damage_max"));
+			targ.leanangle_damage_force_y = bound(-cvar("g_leanplayer_damage_max"), targ.leanangle_damage_force_y, cvar("g_leanplayer_damage_max"));
+			targ.leanangle_damage_force_z = bound(-cvar("g_leanplayer_damage_max"), targ.leanangle_damage_force_z, cvar("g_leanplayer_damage_max"));
+		}
 	}
 
 	// apply push