set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate"\r
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"\r
\r
+set g_leanplayer_damage 0.1 "lean players that are shot by this amount, based on the force they take"\r
+set g_leanplayer_damage_fade 0.001 "how fast players return to normal angles, based on damage taken"\r
+set g_leanplayer_damage_max 10 "damage leaning is limited to this amount"\r
+set g_leanplayer_acceleration 0.05 "lean players as they accelerate, by this amount"\r
+set g_leanplayer_acceleration_fade 5 "velocity averaging steps for acceleration, higher values cause a shorter leaning"\r
+set g_leanplayer_acceleration_max 10 "acceleration leaning is limited to this amount"\r
+\r
set sv_gibhealth -150 "Amount of health a dead body must have in order to get gibbed, influenced by player size"\r
\r
// fragmessage: This allows extra information to be displayed with the frag centerprints. \r
\r
self.angles_z = 0; // never spawn tilted even if the spot says to\r
self.fixangle = TRUE; // turn this way immediately\r
+ self.leanangle_damage_force = '0 0 0';\r
self.velocity = '0 0 0';\r
self.avelocity = '0 0 0';\r
self.punchangle = '0 0 0';\r
*/\r
void() ctf_setstatus;\r
.float items_added;\r
+.vector avg_vel;\r
void PlayerPreThink (void)\r
{\r
self.stat_game_starttime = game_starttime;\r
self.fixangle = TRUE;\r
}\r
\r
+ if(!self.stat_eaten)\r
+ {\r
+ // lean the player with damage and acceleration\r
+ // credits go to divVerent for these maths :)\r
+ vector L0, L1, LF, LA;\r
+\r
+ LA = AnglesTransform_FromAngles(self.angles);\r
+\r
+ // acceleration leaning\r
+ if(cvar("g_leanplayer_acceleration"))\r
+ {\r
+ // average velocity to obtain a smooth acceleration\r
+ float f;\r
+ f = frametime * cvar("g_leanplayer_acceleration_fade");\r
+ self.avg_vel = self.avg_vel * (1 - f) + self.velocity * f;\r
+ }\r
+\r
+ vector accel;\r
+ accel = self.velocity - self.avg_vel * cvar("g_leanplayer_acceleration"); // acceleration\r
+\r
+ // bound angles to the specified limit\r
+ accel_x = bound(-cvar("g_leanplayer_acceleration_max"), accel_x, cvar("g_leanplayer_acceleration_max"));\r
+ accel_y = bound(-cvar("g_leanplayer_acceleration_max"), accel_y, cvar("g_leanplayer_acceleration_max"));\r
+ accel_z = bound(-cvar("g_leanplayer_acceleration_max"), accel_z, cvar("g_leanplayer_acceleration_max"));\r
+\r
+ L0_x = vlen(accel);\r
+ L0_y = L1_y = vectoyaw(accel);\r
+\r
+ L0 = AnglesTransform_FromAngles(L0);\r
+ L1 = AnglesTransform_FromAngles(L1);\r
+ LF = AnglesTransform_Multiply(AnglesTransform_Invert(L1), L0);\r
+ LA = AnglesTransform_Multiply(LA, LF);\r
+ // end of acceleration leaning\r
+\r
+ // damage leaning\r
+ L0 = vectoangles(self.leanangle_damage_loc);\r
+ L1 = vectoangles(self.leanangle_damage_loc + self.leanangle_damage_force);\r
+\r
+ L0 = AnglesTransform_FromAngles(L0);\r
+ L1 = AnglesTransform_FromAngles(L1);\r
+ LF = AnglesTransform_Multiply(AnglesTransform_Invert(L1), L0);\r
+\r
+ LA = AnglesTransform_Multiply(LA, LF);\r
+\r
+ // fade the player back to normal rotation each frame, based on how much damage they have taken\r
+ // this is used to simulate damage, so a wounded player will get back up slower\r
+ if(self.leanangle_damage) // prevent division by zero\r
+ if(self.leanangle_damage_force) // extra safety\r
+ {\r
+ float leanangle_damage_fade;\r
+ leanangle_damage_fade = 1 / (1 + (self.leanangle_damage * cvar("g_leanplayer_damage_fade")));\r
+ self.leanangle_damage_force = self.leanangle_damage_force * leanangle_damage_fade;\r
+ }\r
+ // end of damage leaning\r
+\r
+ self.angles = AnglesTransform_Normalize(AnglesTransform_ToAngles(LA), TRUE);\r
+ }\r
+\r
SetPlayerSize();\r
\r
if(frametime)\r
entity timeoutInitiator; // contains the entity of the player who started the last timeout\r
float orig_slowmo; // contains the value of cvar("slowmo") so that, after timeout finished, it isn't set to slowmo 1 necessarily\r
.vector lastV_angle; //used when pausing the game in order to force the player to keep his old view angle fixed\r
+.vector leanangle_damage_loc, leanangle_damage_force; // used for leaning the player model\r
+.float leanangle_damage;\r
entity timeoutHandler; //responsible for centerprinting the timeout countdowns and playing sounds\r
void timeoutHandler_Think();\r
void evaluateTimeout();\r
}\r
}\r
}\r
+\r
+ // lean the player based on the amount of damage taken\r
+ if(cvar("g_leanplayer_damage"))\r
+ {\r
+ targ.leanangle_damage_loc = hitloc - targ.origin;\r
+ targ.leanangle_damage_force += force * cvar("g_leanplayer_damage"); // keep existing force if any\r
+ targ.leanangle_damage = damage;\r
+\r
+ // bound angles to the specified limit\r
+ targ.leanangle_damage_force_x = bound(-cvar("g_leanplayer_damage_max"), targ.leanangle_damage_force_x, cvar("g_leanplayer_damage_max"));\r
+ targ.leanangle_damage_force_y = bound(-cvar("g_leanplayer_damage_max"), targ.leanangle_damage_force_y, cvar("g_leanplayer_damage_max"));\r
+ targ.leanangle_damage_force_z = bound(-cvar("g_leanplayer_damage_max"), targ.leanangle_damage_force_z, cvar("g_leanplayer_damage_max"));\r
+ }\r
}\r
\r
// apply push\r