Skip to content

Commit

Permalink
CLIENT: Add Hold Breath to Steady Rifle
Browse files Browse the repository at this point in the history
  • Loading branch information
MotoLegacy committed Nov 28, 2024
1 parent ee349fc commit a9cc266
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 8 deletions.
2 changes: 2 additions & 0 deletions source/client/defs/custom.qc
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ float active_achievement;
float current_achievement_page;
float achievement_pages;

float sniper_hold_breath;


float K_LEFTDOWN, K_RIGHTDOWN, K_BACKDOWN, K_FORWARDDOWN;

Expand Down
43 changes: 43 additions & 0 deletions source/client/hud.qc
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,49 @@ void() Draw_Crosshair =
drawfill('0 0 0', [g_width/2 - g_height/2, g_height, 0], '0 0 0', 1, 0);
drawpic([(g_width/2 - g_height/2),0,0], "gfx/hud/scope_nb.tga", [g_height, g_height, 1], [1,1,1], 1);
drawfill([(g_width/2 + g_height/2),0,0], [g_width, g_height, 0], '0 0 0', 1, 0);

// Draw "Hold Breath" text if we aren't already doing so and we don't have Deadshot Daiquiri.
if (sniper_hold_breath != true && !(getstatf(STAT_PERKS) & P_DEAD)) {
// Grab the bind for Sprint/Hold Breath
string breath_button = "";
string space_width = "";

float argc = tokenize(findkeysforcommandex("impulse 23"));
for (int i = 0; i < argc; i++) {
breath_button = strtoupper(argv(i));
float bind_is_gamepad = Key_IsControllerGlyph(breath_button);

if (bind_is_gamepad && last_input_was_gamepad)
break;
else if (!bind_is_gamepad && !last_input_was_gamepad)
break;
}

if (breath_button == "")
breath_button = "UNBOUND";

string breath_button_string = " ";

// If this is a gamepad button, the space we want to reserve
// in the string should be a fixed width.
if (!Key_IsControllerGlyph(breath_button)) {
breath_button_string = breath_button;
}

string breath_string = strcat("Hold ", breath_button_string, " to steady");
float print_width = getTextWidth(breath_string, 12);
float x = (g_width - print_width)/2;
Draw_String([x, 65, 0], breath_string, [12, 12, 0], [1, 1, 1], 1, 0);

// Draw highlighted button
float button_width = x + getTextWidth("Hold ", 12);

if (Key_IsControllerGlyph(breath_button))
Key_DrawControllerGlyph([button_width - 5, 62], breath_button, [18, 18]);
else
Draw_String([button_width, 65, 0], breath_button, [12, 12, 0], [1, 1, 0], 1, 0);
}

return;
}

Expand Down
103 changes: 95 additions & 8 deletions source/client/main.qc
Original file line number Diff line number Diff line change
Expand Up @@ -609,22 +609,102 @@ float(float a) angledelta =
}

//MOVEME
float delta_pitch, delta_yaw;
vector current_sway;
float current_intensity;
float target_intensity;
vector sniper_sway;
// Sways the camera while scoped in.
void() Camera_SniperSway =
float sniper_breath_starttime;
float sniper_breath_endtime;
float sniper_breath_counter;
float sniper_breath_exhaustion_starttime;
float sniper_breath_exhaustion_endtime;
float sniper_breath_delay;
float sniper_hold_breath;

#define SNIPER_SWAY_INTENSITY_FOCUSED 0.05
#define SNIPER_SWAY_INTENSITY_NORMAL 0.5
#define SNIPER_SWAY_INTENSITY_EXHAUSTION 2

void(float inhale) Sniper_HoldBreath =
{
if (sniper_breath_delay > time)
return;

if (getstatf(STAT_WEAPONZOOM) != 2 || (getstatf(STAT_PERKS) & P_DEAD)) {
sniper_sway = '0 0 0';
return;
}

delta_pitch = (cos(cltime/0.7) + cos(cltime) + sin(cltime/1.1)) * 0.5;
delta_yaw = (sin(cltime/0.4) + cos(cltime/0.56) + sin(cltime)) * 0.5;
if (inhale) {
if (sniper_hold_breath == true)
return;
sniper_breath_starttime = time;
sniper_breath_endtime = time + 4;
sniper_hold_breath = true;
localsound("sounds/player/inhale.wav", 0, 1);
} else {
if (sniper_hold_breath == false)
return;
sniper_breath_endtime = sniper_breath_starttime = 0;
sniper_hold_breath = false;
sniper_breath_delay = time + 1;
localsound("sounds/player/exhale.wav", 0, 1);
}
};

void() Camera_SniperSway =
{
// Determine target intensity based on state
target_intensity = SNIPER_SWAY_INTENSITY_NORMAL;

if (getstatf(STAT_WEAPONZOOM) != 2 || (getstatf(STAT_PERKS) & P_DEAD)) {
current_intensity = 0;
current_sway = '0 0 0';
target_intensity = 0;
sniper_breath_counter = 0;
} else {
// We are focused.
if (sniper_breath_endtime > time) {
target_intensity = SNIPER_SWAY_INTENSITY_FOCUSED;

float breath_duration = floor(time - sniper_breath_starttime);

sniper_sway[0] = angledelta(delta_pitch);
sniper_sway[1] = angledelta(delta_yaw);
// Play heartbeat sfx at every second interval.
if (breath_duration != sniper_breath_counter) {
sniper_breath_counter = breath_duration;
localsound("sounds/player/heart.wav", 0, 5);
}
}
// Time has expired and we're out of breath, begin exhaustion.
else if (sniper_breath_endtime < time && sniper_hold_breath == true) {
Sniper_HoldBreath(false);
sniper_breath_exhaustion_starttime = time;
sniper_breath_exhaustion_endtime = time + 4;
sniper_breath_delay = time + 4;
}

// Slowly decrease in intensity from fully exhausted to normal.
if (sniper_breath_exhaustion_endtime > time) {
float progress = (time - sniper_breath_exhaustion_starttime) / (sniper_breath_exhaustion_endtime - sniper_breath_exhaustion_starttime);
target_intensity = SNIPER_SWAY_INTENSITY_EXHAUSTION + progress * (SNIPER_SWAY_INTENSITY_NORMAL - SNIPER_SWAY_INTENSITY_EXHAUSTION);
}
}

// Smoothly interpolate intensity towards target
current_intensity += (target_intensity - current_intensity) * (clframetime * 5); // Adjust 0.1 for smoother/faster transitions

// Calculate sway deltas based on cltime and intensity
float sway_pitch = (cos(cltime / 0.7) + cos(cltime) + sin(cltime / 1.1));
float sway_yaw = (sin(cltime / 0.4) + cos(cltime / 0.56) + sin(cltime));

// Update current sway using the smoothly interpolated intensity
current_sway[0] = sway_pitch * current_intensity;
current_sway[1] = sway_yaw * current_intensity;

// Apply the smooth sway to sniper_sway
sniper_sway[0] = angledelta(current_sway[0]);
sniper_sway[1] = angledelta(current_sway[1]);
};

float gamepad_enabled;

// CALLED EVERY CLIENT RENDER FRAME
Expand Down Expand Up @@ -782,6 +862,13 @@ void(float scanx, float setval) Input_Movecheck =
tokenize(findkeysforcommand("+back"));
if (scanx == stof(argv(0)))
K_BACKDOWN = setval;

float argc = tokenize(findkeysforcommand("impulse 23"));
for (int i = 0; i < argc; i++) {
if (scanx == stof(argv(i))) {
Sniper_HoldBreath(setval);
}
}
}

noref float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent =
Expand Down

0 comments on commit a9cc266

Please sign in to comment.